jsoneditor
jsoneditor copied to clipboard
React function component: Cannot read property 'catch' of undefined
Hi, thanks for the great job. I am using jsoneditor with react and function component. Everything goes fine, but when I trigger updating using onChangeJSON and then an error thrown.
Cannot read property 'catch' of undefined
Demo code: https://codesandbox.io/s/9sljv
Hi, thanks! It looks like your demo code is incomplete: the file editor.jsx
containing the CustomJSONEditor
is empty.
Have you seen the React examples that come with the library? See:
- https://github.com/josdejong/jsoneditor/tree/develop/examples/react_demo
- https://github.com/josdejong/jsoneditor/tree/develop/examples/react_advanced_demo
@josdejong Sorry, I forgot to save the files and have added sample codes now. I have seen the examples and want to make it with React Hooks.
Ah, now I get something: I get an error "this.validate() is undefined".
I think the cause is that in your code example, with every change in your json, you destroy the editor and create a new one. It would be good if the editor is robust against this and doesn't give this error (this.validate()
is running in a debounced function, and when it executes, the editor is destroyed already). But anyway you should make sure the editor is only instantiated once, else you will lose your state (scroll bar position, cursor, expanded nodes, etc) with every change you make, which is not workable.
Thanks @josdejong It works when I remove the destroy code in the useEffect, and I am now wondering if I have to destroy the instance when the page unmounts.
Yes normally you have to destroy the instance when your component unmounts. If you don't do that, you can get memory leakage (holding more and more jsoneditors in memory).
@josdejong, @xyxc0673, would you let me know what is the final solution?
export const JsonEditor: FC<IJsonEditorProps> = memo(
({ schema, mode, initialJsonValue, onChange }: IJsonEditorProps) => {
const validate = ajv.compile(schema)
const containerRef = useRef<HTMLDivElement | null>(null)
const editorRef = useRef<JSONEditor | null>(null)
const handleChange = () => {
console.log(onChange)
if (onChange && editorRef.current && validate) {
let json = editorRef.current.get()
const isJsonValid = validate(json)
if (isJsonValid) {
onChange(json)
} else {
onChange(null)
}
}
}
useEffect(() => {
if (containerRef.current != null) {
console.log("here", containerRef.current, editorRef.current)
if (editorRef.current != null) {
editorRef.current.setSchema(schema)
editorRef.current.set(initialJsonValue)
if (mode) {
editorRef.current.setMode(mode)
}
} else {
editorRef.current = new JSONEditor(containerRef.current, {
schema: schema,
mode: "tree",
indentation: 4,
onChange: handleChange,
})
editorRef.current.set(initialJsonValue)
}
}
}, [containerRef, initialJsonValue, schema, mode])
useEffect(() => () => {
editorRef.current?.destroy()
}, [])
return (
<div
className="jsoneditor-react-container"
ref={containerRef}
/>
)
}
)
Thanks for sharing your solution @marindrag
A bit off-topic: I haven't worked out an example with react hooks for jsoneditor
, but did so for the successor, svelte-jsoneditor
: https://codesandbox.io/s/svelte-jsoneditor-react-59wxz?file=/src/SvelteJSONEditor.js which as an API which is better aligned to use within React or an other framework.