Búsqueda de sitios web

javascript - Slate.js lanza un error al insertar un nuevo nodo en la región seleccionada


Bloques de código relevantes:

        <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, opts, defaultValue, children: [{text: ''}] }
    Transforms.insertNodes(editor, templateBlock);
    Transforms.move(editor);
}

Específicamente, siempre se rompe en la segunda línea dentro de la función insertTemplateBlock, dando un error parecido a:

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,0],"offset":19}},"newProperties":{"anchor":{"path":[0,0],"offset":17}}},{"type":"remove_text","path":[0,0],"offset":17,"text":"{{"},{"type":"insert_node","path":[0,1],"node":{"type":"template-block","name":"test","children":[{"text":""}]}},{"type":"set_selection","properties":{"anchor":{"path":[0,0],"offset":17},"focus":{"path":[0,0],"offset":17}},"newProperties":{"anchor":{"path":[0,1,0],"offset":0},"focus":{"path":[0,1,0],"offset":0}}},{"type":"insert_node","path":[0,2],"node":{"text":""}},{"type":"set_selection","properties":{"anchor":{"path":[0,1,0],"offset":0},"focus":{"path":[0,1,0],"offset":0}},"newProperties":{"anchor":{"path":[0,2],"offset":0},"focus":{"path":[0,2],"offset":0}}}],"selection":{"anchor":{"path":[0,2],"offset":0},"focus":{"path":[0,2],"offset":0}},"marks":null,"history":{"undos":[[{"type":"set_selection","properties":null,"newProperties":{"anchor":{"path":[0,0],"offset":0},"focus":{"path":[0,0],"offset":0}}}],[{"type":"insert_text","path":[0,0],"offset":0,"text":"T"},{"type":"insert_text","path":[0,0],"offset":1,"text":"h"},{"type":"insert_text","path":[0,0],"offset":2,"text":"i"},{"type":"insert_text","path":[0,0],"offset":3,"text":"n"},{"type":"insert_text","path":[0,0],"offset":4,"text":"g"},{"type":"insert_text","path":[0,0],"offset":5,"text":" "},{"type":"insert_text","path":[0,0],"offset":6,"text":"i"},{"type":"insert_text","path":[0,0],"offset":7,"text":"s"},{"type":"insert_text","path":[0,0],"offset":8,"text":" "},{"type":"insert_text","path":[0,0],"offset":9,"text":"w"},{"type":"insert_text","path":[0,0],"offset":10,"text":"o"},{"type":"insert_text","path":[0,0],"offset":11,"text":"r"},{"type":"insert_text","path":[0,0],"offset":12,"text":"k"},{"type":"insert_text","path":[0,0],"offset":13,"text":"i"},{"type":"insert_text","path":[0,0],"offset":14,"text":"n"},{"type":"insert_text","path":[0,0],"offset":15,"text":"g"},{"type":"insert_text","path":[0,0],"offset":16,"text":" "},{"type":"set_selection","properties":null,"newProperties":{"anchor":{"path":[0,0],"offset":17},"focus":{"path":[0,0],"offset":17}}}],[{"type":"insert_text","path":[0,0],"offset":17,"text":"{"},{"type":"insert_text","path":[0,0],"offset":18,"text":"{"},{"type":"set_selection","properties":{"anchor":{"path":[0,0],"offset":19}},"newProperties":{"anchor":{"path":[0,0],"offset":17}}},{"type":"remove_text","path":[0,0],"offset":17,"text":"{{"},{"type":"insert_node","path":[0,1],"node":{"type":"template-block","name":"test","children":[{"text":""}]}},{"type":"set_selection","properties":{"anchor":{"path":[0,0],"offset":17},"focus":{"path":[0,0],"offset":17}},"newProperties":{"anchor":{"path":[0,1,0],"offset":0},"focus":{"path":[0,1,0],"offset":0}}},{"type":"insert_node","path":[0,2],"node":{"text":""}},{"type":"set_selection","properties":{"anchor":{"path":[0,1,0],"offset":0},"focus":{"path":[0,1,0],"offset":0}},"newProperties":{"anchor":{"path":[0,2],"offset":0},"focus":{"path":[0,2],"offset":0}}}]],"redos":[]}}

Esto no sucede en su ejemplo de menciones, que utiliza una lógica similar. ¡Cualquier ayuda sería apreciada!

Codesandbox: https://codesandbox.io/s/elastic-turing-dv9bm?file=/src/App.tsx

ACTUALIZACIÓN: Desde entonces he descubierto que este problema se puede evitar moviendo la lógica de inserción (actualmente en la instrucción if) a un hook useEffect dependiendo de un valor target que contenga la selección, de manera similar a cómo funciona el ejemplo de menciones de Slate. Sin embargo, todavía tengo curiosidad por saber por qué Slate se rompe de la forma en que lo hace cuando lo escribo de la manera indicada en la declaración de la pregunta.

Respuesta #1

El problema está relacionado con el renderizado cuando usas useMemo, en su lugar deberías usar useRef:

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

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

Respuesta #2

Creo que tu problema se debe al hecho de que <Slate> es el proveedor de contexto, y en realidad deberías estar usando un componente <Editable> anidado para manejar eventos, en tu caso onKeyDown. En el ejemplo específico que mencionaste, creo que te estás encontrando con una condición de carrera que no ocurrirá con el componente Editable anidado. Consulta Instalando Slate en Guías paso a paso en la documentación.

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

Artículos relacionados