ianstormtaylor / slate

A completely customizable framework for building rich text editors. (Currently in beta.)
http://slatejs.org
MIT License
29.87k stars 3.25k forks source link

Manually setting the value in the editor does not update. #5418

Open ABCDdouyaer opened 1 year ago

ABCDdouyaer commented 1 year ago

Manually setting the value in the editor does not update. Is there any other way for me to manually change the value and update it? `


import { useState } from 'react';
import { Slate, Editable, withReact } from 'slate-react';
import { createEditor } from 'slate';

function EditorExample() {
  const editor = useMemo(() => withReact(createEditor()), []);
  const [value, setValue] = useState([
    {
      type: 'paragraph',
      children: [{ text: 'Hello, world!' }],
    },
  ]);

  const handleChange = (newValue) => {
    setValue(newValue);
  };

  const handleButtonClick = () => {
    const newValue = [
      {
        type: 'paragraph',
        children: [{ text: 'New value!' }],
      },
    ];
    setValue(newValue);
  };

  return (
   <div>
     <button onClick={handleButtonClick}>Update value</button>
     <Slate editor={editor} value={value} onChange={handleChange}>
      < Editable />
      </Slate>
    </div>
  );
}`
e1himself commented 1 year ago

@ABCDdouyaer I understand your confusion, but value is really initialValue. It is only used for the initialization. For the rest of the editor lifetime it does nothing.

See:

hamaddo commented 1 year ago

@ABCDdouyaer you can update value by using this function:

export const resetNodes = (
  editor: Editor,
  options: {
    nodes?: Node | Node[];
    at?: Location;
  } = {},
): void => {
  const cachedSelection = editor.selection;
  const children = [...editor.children];
  for (let i = 0; i < children.length; i++) {
    const node = children[i];
    editor.apply({ type: 'remove_node', path: [0], node });
  }

  if (options.nodes) {
    const nodes = Node.isNode(options.nodes) ? [options.nodes] : options.nodes;
    for (let i = 0; i < nodes.length; i++) {
      editor.apply({ type: 'insert_node', path: [i], node: nodes[i] });
    }
  }

  if (cachedSelection && Point.isBefore(cachedSelection.anchor, Editor.end(editor, []))) {
    Transforms.select(editor, cachedSelection);
    return;
  }
  Transforms.select(editor, Editor.end(editor, []));
};

just call it in useEffect or somewhere else

  useEffect(() => {
    resetNodes(editor, { nodes: value });
  }, [value]);
andregueva commented 1 year ago

@hamaddo I have doubts where do I get Point? in this line Point.isBefore(cachedSelection.anchor, Editor.end(editor, []))

thanks.

SantosOMartinez commented 4 months ago

@hamaddo I have doubts where do I get Point? in this line Point.isBefore(cachedSelection.anchor, Editor.end(editor, []))

thanks.

@andregueva you can import it from the slate library:

import { Point } from 'slate';