Slate.js 在选定区域插入新节点时抛出错误

问题描述

相关代码块:

        <Slate editor={editor} value={value} onChange={value => {
            setValue(value);

            const { selection } = editor;
            // if nothing is currently selected under the cursor
            if (selection && Range.isCollapsed(selection)) {
                const [start] = Range.edges(selection);
                // if the two characters beforce the cursor are {{,select them and replace with a template block
                const before = Editor.before(editor,start,{distance: 2})
                const beforeRange = before && Editor.range(editor,before,start)
                const beforeText = beforeRange && Editor.string(editor,beforeRange)
                const beforeMatch = beforeText && beforeText.match(/\{\{/);
                if (beforeMatch) {
                    Transforms.select(editor,beforeRange as Location);
                    insertTemplateBlock(editor,{name: "test"})
                }
            }
        }}>
...
</Slate>
export const insertTemplateBlock = (editor: Editor,{name,opts,defaultValue}: TemplateBlockProps) => {
    const templateBlock = { type: "template-block",name,defaultValue,children: [{text: ''}] }
    Transforms.insertNodes(editor,templateBlock);
    Transforms.move(editor);
}

特别是,它总是在 insertTemplateBlock 函数内的第二行中断,给出如下错误:

Cannot find a descendant at path [0,2] in node: {"children":[{"type":"paragraph","children":[{"text":"Thing is working {{"}]}],"operations":[{"type":"insert_text","path":[0,0],"offset":18,"text":"{"},{"type":"set_selection","properties":{"anchor":{"path":[0,"offset":19}},"newProperties":{"anchor":{"path":[0,"offset":17}}},{"type":"remove_text","offset":17,"text":"{{"},{"type":"insert_node",1],"node":{"type":"template-block","name":"test","children":[{"text":""}]}},"offset":17},"focus":{"path":[0,"offset":17}},1,"offset":0},"offset":0}}},2],"node":{"text":""}},"offset":0}},"offset":0}}}],"selection":{"anchor":{"path":[0,"marks":null,"history":{"undos":[[{"type":"set_selection","properties":null,[{"type":"insert_text","offset":0,"text":"T"},{"type":"insert_text","offset":1,"text":"h"},"offset":2,"text":"i"},"offset":3,"text":"n"},"offset":4,"text":"g"},"offset":5,"text":" "},"offset":6,"offset":7,"text":"s"},"offset":8,"offset":9,"text":"w"},"offset":10,"text":"o"},"offset":11,"text":"r"},"offset":12,"text":"k"},"offset":13,"offset":14,"offset":15,"offset":16,"offset":17}}}],"offset":0}}}]],"redos":[]}}

这不会发生在他们提到的例子中,它使用了类似的逻辑。任何帮助将不胜感激!

代码沙盒:https://codesandbox.io/s/elastic-turing-dv9bm?file=/src/App.tsx

更新:我后来发现可以通过将插入逻辑(当前在 if 语句中)移动到 useEffect 钩子来避免这个问题,这取决于包含选择的 target 值,类似Slate 的提及示例如何工作。但是,我仍然很想知道为什么 Slate 在我以问题陈述的方式编写时会破坏它的方式。

解决方法

该问题与您使用 useMemo 时的渲染有关,而您应该使用 useRef

const editorRef = useRef()
if (!editorRef.current) editorRef.current = withReact(createEditor())
const editor = editorRef.current

https://github.com/ianstormtaylor/slate/issues/4081

,

我认为您的问题源于 <Slate> 是上下文提供者,您实际上应该使用嵌套的 <Editable> 组件来处理事件 - 在您的情况下为 onKeyDown。在您提到的具体示例中,我相信您遇到了嵌套 Editable 组件不会发生的竞争条件。请参阅文档中演练下的安装 Slate

https://docs.slatejs.org/walkthroughs/01-installing-slate

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...