React Widget
Build a JSONata editor into your React app with hooks, components, and live evaluation
React Widget Tutorial
Build a JSONata editor into a React app with syntax highlighting, autocomplete, hover docs, and live evaluation.
This is what the finished editor looks like — try editing the expression:
Prerequisites
- Node.js 18+
- React 18+ project
Step 1: Install
npm install @gnata-sqlite/reactStep 2: Copy LSP WASM to public
The package ships pre-built WASM binaries for the editor LSP (autocomplete, diagnostics, hover). Copy them to your app's public directory:
npx @gnata-sqlite/react setup ./publicThis copies gnata-lsp.wasm (380 KB, 145 KB gzipped) and lsp-wasm_exec.js (16 KB) into public/.
Step 3: Editor with full language support
The useJsonataLsp hook loads the LSP WASM automatically — no configuration needed:
import { JsonataEditor, useJsonataLsp, useJsonataSchema } from '@gnata-sqlite/react'
import { useState } from 'react'
export default function App() {
const [expression, setExpression] = useState('Account.Name')
const [inputJson] = useState('{"Account":{"Name":"Firefly"}}')
const lsp = useJsonataLsp()
const schema = useJsonataSchema(inputJson)
return (
<JsonataEditor
value={expression}
onChange={setExpression}
schema={schema}
gnataDiagnostics={lsp.gnataDiagnostics}
gnataCompletions={lsp.gnataCompletions}
gnataHover={lsp.gnataHover}
theme="dark"
/>
)
}Step 4: Custom layout with individual components
import {
JsonataEditor, JsonataInput, JsonataResult,
useJsonataLsp, useJsonataSchema,
} from '@gnata-sqlite/react'
import { useState } from 'react'
export default function CustomEditor() {
const [expression, setExpression] = useState('Account.Name')
const [inputJson, setInputJson] = useState('{"Account":{"Name":"Firefly"}}')
const lsp = useJsonataLsp()
const schema = useJsonataSchema(inputJson)
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
<JsonataEditor
value={expression} onChange={setExpression}
schema={schema}
gnataDiagnostics={lsp.gnataDiagnostics}
gnataCompletions={lsp.gnataCompletions}
gnataHover={lsp.gnataHover}
theme="dark"
getInputJson={() => inputJson}
/>
<JsonataInput value={inputJson} onChange={setInputJson} theme="dark" />
</div>
)
}Step 5: Client-side evaluation (optional)
For the rare case where evaluation must run in the browser, load the full eval engine (~5.3MB). This is opt-in — most apps evaluate server-side.
import {
JsonataPlayground,
useJsonataWasm, useJsonataEval, useJsonataSchema,
} from '@gnata-sqlite/react'
// Evaluation engine must be built from source and served separately:
// make wasm
// cp gnata.wasm wasm_exec.js public/
const wasm = useJsonataWasm({
evalWasmUrl: '/gnata.wasm',
evalExecUrl: '/wasm_exec.js',
})
const { result, error, timing } = useJsonataEval(expr, inputJson, wasm.gnataEval)Or use the all-in-one playground component:
<JsonataPlayground
defaultExpression="$sum(Account.Order.Product.(Price * Quantity))"
defaultInput={sampleData}
wasmOptions={{
evalWasmUrl: '/gnata.wasm',
evalExecUrl: '/wasm_exec.js',
}}
theme="dark"
height={400}
/>Step 6: Syntax highlighting only (no WASM)
<JsonataEditor value={expression} onChange={setExpression} theme="dark" />No WASM function props = no WASM loading. Highlighting works instantly with the tokenizer only.
Next Steps
- React Widget API Reference — full props, hooks, and types
- Editor & LSP API — low-level CodeMirror and WASM exports
- TinyGo WASM — why the LSP is 145 KB