Reputation: 4192
I have this component:
import "./styles.css";
import React, { useEffect, useRef, useState } from "react";
import JSONEditor from "jsoneditor";
import "jsoneditor/dist/jsoneditor.css";
const JSONReact = ({ json, mode, onChange }) => {
const ref1 = useRef(null);
const ref2 = useRef(null);
useEffect(() => {
const props = {
onChangeText: (value) => {
console.log(value, "vv");
onChange(value);
},
modes: ["code"]
};
ref1.current = new JSONEditor(ref2.current, props);
if (json) {
ref1.current.set(json);
}
return () => {
ref1.current.destroy();
};
}, []);
useEffect(() => {
if (json) {
ref1?.current.update(json);
}
}, [json]);
return <div ref={ref2} />;
};
export default function App() {
const [state, setState] = useState('{"cars": "22w-08w-23"}');
const onChange = (j) => {
console.log(j);
setState(j);
};
return (
<div className="App">
<JSONReact mode="code" onChange={onChange} json={JSON.parse(state)} />
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
When i type something inside editor i get undefined in console.log(j);
, but i don't understand why. Who can help to fix it?
https://codesandbox.io/s/admiring-khorana-pdem1l?file=/src/App.js:909-929
Upvotes: 0
Views: 925
Reputation:
Well it is expected as in the docs it clearly says "This callback does not pass the changed contents", over here https://github.com/josdejong/jsoneditor/blob/master/docs/api.md#:~:text=This%20callback%20does%20not%20pass%20the%20changed%20contents
However, There are two ways to do it, that I found from here
https://github.com/josdejong/jsoneditor/blob/master/docs/api.md#configuration-options
First Way: use getText() from JSONEditor object to get the current value, since it will return you string so just parse it in json and pass inside your callback (onChange) prop.
const props = {
onChange: () => {
onChange(JSON.parse(ref1.current.getText()));
},
modes: ["code"]
};
ref1.current = new JSONEditor(ref2.current, props);
Second way: just use onChangeText and it will give the string in the callback,
const props = {
onChangeText: (value) => {
onChange(JSON.parse(value));
},
modes: ["code"]
};
ref1.current = new JSONEditor(ref2.current, props);
EDIT 1: added JSON validation check before calling onChange Props
const isValidJSON = (jsonString) => {
try {
JSON.parse(jsonString);
} catch (e) {
return false;
}
return true;
};
useEffect(() => {
const props = {
onChangeText: (value) => {
isValidJSON(value) && onChange(JSON.parse(value));
},
modes: ["code"]
};
ref1.current = new JSONEditor(ref2.current, props);
EDIT 2: adding error validation using validate()
, here in this case we can remove isValidJSON(value)
check from below code since we are already checking for JSON errors using validate()
.
onChangeText: (value) => {
const errors = ref1.current.validate();
errors.then((err) => {
if (!err.length) {
isValidJSON(value) && onChange(JSON.parse(value));
} else {
console.log(err);
}
});
}
Upvotes: 2
Reputation: 866
I think it is a normal behaviour of JSONEditor, according to docs:
{function} onChange()
Set a callback function triggered when the contents of the JSONEditor change. This callback does not pass the changed contents, use get() or getText() for that. Note that get() can throw an exception in mode text, code, or preview, when the editor contains invalid JSON. Will only be triggered on changes made by the user, not in case of programmatic changes via the functions set, setText, update, or updateText. See also callback functions onChangeJSON(json) and onChangeText(jsonString). `
Upvotes: 0