简体   繁体   中英

Reactjs - CKEditor onchange lift up state

I manage to set up CKEditor and it works great. My problem is I'm refactoring the code and I need the editor component to be called by several other components.

So, my handleChange is not really working anymore. How can I pass only data to parent's handleChange function?

parent:

function IncluirArtigo() {

    const campos = { autor: '', titulo: '', texto: '' };

    const [valores, setValores] = useState(campos);
    const [erro, setErro] = useState(false);
    const history = useHistory();

    const handleChange = e => {
        setValores({
            ...valores,
            [e.target.name]: e.target.value
        });
        console.log(valores)
    }

    const incluir = async (e) => {
        e.preventDefault();

        console.log(valores);
        
        try {
            //await PostArtigo(valores);
            /* Poderia redirecionar para o artigo criado, se o post retornasse uma id */
            goHome();
        }
        catch (e) {
            console.error('erro', e);
            setErro(true);
        }
    }

    const goHome = () => history.push('/');

    return (
        <div className="container">
            {
                erro ?
                    <div>Houve erro na inclusão do artigo, tente novamente</div>
                    :
                    <>
                        <h3>Inclusão de Artigos</h3>
                        <form onSubmit={incluir} className="form-incluir">
                            <label htmlFor="autor">Autor:</label>
                            <input 
                                type="text" 
                                name="autor" 
                                value={valores.autor}
                                onChange={handleChange}
                            />
                            <label htmlFor="titulo">Título:</label>
                            <input 
                                type="text" 
                                name="titulo" 
                                value={valores.titulo}
                                onChange={handleChange}    
                                />
                            <label>Conteúdo:</label>
                            <div className="editor">
                                <Editor />
                            </div>
                            <input className="btn-enviar" type="submit" value="Enviar" />
                        </form>
                    </>
            }
        </div >
    )
}

editor.js

function Editor() {

    return (
        <div className="editor">
            <CKEditor
                editor={ClassicEditor}
                data={valores.texto}
                onChange={(event, editor) => {
                    const texto = editor.getData();
                    console.log({ event, editor, texto });
                    handleChange() /* I need this function to pass only valores data */
                }}
            />
        </div>
    )
}

Method 1: Parent Controls the Text

We can make the editor into a controlled component by passing down the value from the parent and also using an onChange callback to update the value in the parent.

function Editor({ texto, onChangeTexto }) {
  return (
    <div className="editor">
      <CKEditor
        editor={ClassicEditor}
        data={texto}
        onChange={(event, editor) => {
          onChangeTexto(editor.getData());
        }}
      />
    </div>
  );
}
<Editor
  texto={valores.texto}
  onChangeTexto={(texto) => {
    setValores({ ...valores, texto });
  }}
/>

Method 2: Parent Accesses Editor Instance

The CKEditor component has a prop called onInit which we can use to pass a refence to the editor object to the parent. Instead of updating the state on every change, the parent can get the value of the text from editor.getData() rather than from valores.texto .

function Editor({ onInit }) {
  return (
    <div className="editor">
      <CKEditor
        editor={ClassicEditor}
        onInit={onInit}
      />
    </div>
  );
}

In parent:

const [editor, setEditor] = useState(null);
<Editor
  onInit={setEditor}
/>

To get text ( in submit function )

const texto = editor?.getData();

In this particular case I would probably go with Method 2 as it limits the amount of state changes and re-renders.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM