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
, но, хотя я легко могу передать ссылку на меню, я не понимаю, как получить доступ к выделенному / выделенному тексту редактора, который, по-видимому, ранее был пропущен через реквизит.