Как преобразовать меню наведения Slate JS в React Hooks? - PullRequest
0 голосов
/ 06 октября 2019

Slate JS представляет собой пример довольно гладкого меню при наведении, основанного на традиционном компоненте Class . Моя цель - конвертировать это для использования с React Hooks. Я думаю, что мне 95% пути, но я зациклен на том, как передавать определенные реквизиты из компонента Editor в функцию updateMenu(), которая вызывается функциями жизненного цикла. Вот псевдо-кодовые представления компонентов Class и Hook:

Class

class EditorWithHoveringMenu extends Component {
  menuRef = React.createRef()
  componentDidMount = () => {
    this.updateMenu();
  };
  componentDidUpdate = () => {
    this.updateMenu();
  };
  updateMenu = () => {
    const menu = this.menuRef.current;
    if (!menu) return;

    const { value: {fragment, selection } } = this.props; // the future problem
    ...do more stuff
  }
  renderEditor = (props, editor, next) => {
    const children = next();
    return (
      <React.Fragment>
        {children}
        <HoverMenu ref={this.menuRef} editor={editor} />
      </React.Fragment>
    );
  };
  render() {
    return (
      <Editor
        value={this.props.value}
        renderEditor={this.renderEditor}
      />
  }
}

Hooks

function Editor() {
  const menu = useRef(null);
  const { text, setText } = useContext(EditorContext); // editor state now derived from context

  // In practical terms, this effect should run whenever text is selected/highlighted or deselected.
  useEffect(() => {
    updateMenu(menu, ???);
  });

  const updateMenu = (menuRef, value) => {
    const menu = menuRef.current;
    if (!menu) return;
    const { fragment, selection } = value; // Not sure how to get at these without `this`
    ...do more stuff
  }
  const renderEditor = (props, editor, next) => {
    const children = next();
    return (
      <React.Fragment>
        {children}
        <HoverMenu ref={menu} editor={editor} />
      </React.Fragment>
    );
  };

  return (
    <Editor
      value={Value.fromJSON(text)}
      renderEditor={renderEditor}
    />
  )
}

По сути, я переопределил updateMenu() дляне ссылка this, но, хотя я легко могу передать ссылку на меню, я не понимаю, как получить доступ к выделенному / выделенному тексту редактора, который, по-видимому, ранее был пропущен через реквизит.

1 Ответ

0 голосов
/ 07 октября 2019

Мне удалось решить эту проблему путем проб и ошибок. Изучая исходный пример компонента Class, деструктура const { value: {fragment, selection } } = this.props; ссылается на объект значения slate.js .

Как только я это понял, это было так же просто, как передать копию с значением Value text (из ссылки useContext) в качестве аргумента updateMenu():

const { text, setText } = useContext(EditorContext);

// From this
useEffect(() => {
  updateMenu(menu, ???);
});

// To this
useEffect(() => {
  updateMenu(menu, Value.fromJSON(text));
});
...