Home > Software engineering >  onChange return undefined in ReactJS
onChange return undefined in ReactJS

Time:04-01

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?
demo: https://codesandbox.io/s/admiring-khorana-pdem1l?file=/src/App.js

CodePudding user response:

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 callback does not pass the changed contents

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.

JavaScript

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: 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);

CodePudding user response:

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). `

  • Related