可以在每次渲染时取消订阅并重新订阅我的所有 @Lexical/react 命令侦听器吗?

Mic*_*urz 2 reactjs lexicaljs

在 中,在没有依赖项的数组@lexical/react中注册编辑器命令是否会造成重大损失(性能或其他) ?useEffect

useEffect(() => {
  const unsubscribe = editor.registerCommand(
    KEY_ENTER_COMMAND,
    event => { /* ... */ },
    COMMAND_PRIORITY_HIGH
  )

  return unsubscribe
})
Run Code Online (Sandbox Code Playgroud)

这是对 的内部要求Lexical,还是仅仅是调用一个额外的简单函数的问题?或者这种方法还有其他缺点吗?

zur*_*fyx 5

它相当便宜,在幕后我们只需从地图和集合中添加/删除即可。但如果你不需要做这些,它会更便宜。

useCommandSubscription是一个不错的抽象,一些(未经测试的)代码:

function useCommandSubscription<T>(command: LexicalCommand<T>, fn: CommandListener<T>, priority: CommandListenerPriority): void {
  const [editor] = useLexicalComposerContext();
  useLayoutEffect(() => {
    return editor.registerCommand(command, fn, priority);
  }, [editor]);
}
useCommandSubscription(FOO_COMMAND, () => { ... }, priority);
Run Code Online (Sandbox Code Playgroud)

但请注意如何进一步优化我们提供的开箱即用的功能:

useEffect(() => {
  // You can return immediately, no need to store the cleanup function in a variable
  return editor.registerCommand(...);
}, [editor]);
Run Code Online (Sandbox Code Playgroud)

一个常见的用例是您一次监听多个命令/更新,您可以利用mergeRegister(来自@lexical/utils):

useEffect(() => {
  return mergeRegister(
    editor.registerCommand(..),
    editor.registerCommand(..),
    editor.registerUpdateListener(..),
}, [editor]);
Run Code Online (Sandbox Code Playgroud)

旁注:聆听按键输入命令时要小心。Android 与组合一起工作,不会触发按键输入事件。根据您的用例,您可能想要探索INSERT_LINE_BREAK_COMMAND基于 、INSERT_PARAGRAPH_COMMAND、 的转换LineBreakNode,或者ParagraphNode基于这两个节点的突变侦听器。