Cannot find a descendant at path when emptying deeply nested editor value

See original GitHub issue

I’m integrating the code examples into our app and I’m hitting an issue that might be a bug, or me not understanding how to correctly reset the editor state.

Here’s a quick summary of the React structure of our Composer component:

const EMPTY = [{ children: [{ text: '' }] }];

const [value, setValue] = useState<Node[]>(EMPTY);

<Slate
  editor={editor}
  value={value}
  onChange={(newValue) => setValue(newValue)}
>
  <Editable
    onKeyDown={(event) => {
      if (event.key === 'Enter') {
        event.preventDefault();

        sendMessage(value);

        // clear the input
        Transforms.select(editor, Editor.start(editor, [])); // move the cursor to the beginning of the input before we clear it
        setValue(EMPTY);
      }
    }}
  />
</Slate>

This works fine when the value in the editor is simple, but when the editor has a value that is deeply nested, like a list with one list item:

[
  {
    "type": "ul",
    "children": [
      {
        "type": "li",
        "children": [
          {
            "text": "list item"
          }
        ]
      }
    ]
  }
]

… I get this error in the console after clearing the editor:

Uncaught Error: Cannot find a descendant at path [0,0,0] in node: {“children”:[{“children”:[{“text”:“”}]}],“operations”:[{“type”:“set_selection”,“properties”:{“anchor”:{“path”:[0,0,0],“offset”:4},“focus”:{“path”:[0,0,0],“offset”:4}},“newProperties”:{“anchor”:{“path”:[0,0,0],“offset”:0},“focus”:{“path”:[0,0,0],“offset”:0}}}],“selection”:{“anchor”:{“path”:[0,0,0],“offset”:0},“focus”:{“path”:[0,0,0],“offset”:0}},“marks”:null}

It seems that, even though the selection range was set to empty, it still holds on to the depth information, the fact that the focus was on a node that was 3 levels deep in the value, so I’m guessing either I have to reset the entire path somehow, or this is a bug.

I managed to fix this by changing the clear transform to:

Transforms.select(editor, {
  anchor: { path: [0, 0], offset: 0 },
  focus: { path: [0, 0], offset: 0 },
})

I’m curious if there’s another, more straightforward way to use the Editor API to get the same result.

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:21
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
M162commented, Apr 27, 2022

I see this issue is still open. Any update about this issue? Do we have a better way to solve this?

0reactions
FokkeZBcommented, Aug 29, 2022

We love Slate at Zapier, but run into this issue as well, when a user undo’s pasting a value that results in nodes with an empty leaf text node. This is how we can reproduce:

  1. Initialize with an empty value, which results in children being:
[
  {
    "children": [
      {
        "text": ""
      }
    ],
    "type": "paragraph"
  }
]
  1. Paste something that we translate to:
[
  {
    "type": "paragraph",
    "children": [
      {
        "text": "sdfsdfsdfsdf"
      },
      {
        "type": "mapped-field",
        "value": "166003157__id",
        "children": [
          {
            "text": ""
          }
        ]
      },
      {
        "text": ""
      },
      {
        "type": "mapped-field",
        "value": "166003157__hello",
        "children": [
          {
            "text": ""
          }
        ]
      },
      {
        "text": ""
      }
    ]
  }
]
  1. Undo e.g. via Cmd+Z on Mac.

  2. You’ll get:

This happens after the 2nd of these inverseOps:

[
  {
    "type": "set_selection",
    "properties": {
      "anchor": {
        "path": [
          0,
          0
        ],
        "offset": 0
      },
      "focus": {
        "path": [
          0,
          0
        ],
        "offset": 0
      }
    },
    "newProperties": {
      "anchor": {
        "path": [
          0,
          4
        ],
        "offset": 0
      },
      "focus": {
        "path": [
          0,
          4
        ],
        "offset": 0
      }
    }
  },
  {
    "type": "insert_node",
    "path": [
      0,
      2
    ],
    "node": {
      "text": ""
    }
  },
  {
    "type": "set_selection",
    "properties": {
      "anchor": {
        "path": [
          0,
          5
        ],
        "offset": 0
      },
      "focus": {
        "path": [
          0,
          5
        ],
        "offset": 0
      }
    },
    "newProperties": {
      "anchor": {
        "path": [
          0,
          2
        ],
        "offset": 0
      },
      "focus": {
        "path": [
          0,
          2
        ],
        "offset": 0
      }
    }
  },
  {
    "type": "remove_node",
    "path": [
      0,
      5
    ],
    "node": {
      "text": ""
    }
  },
  {
    "type": "remove_node",
    "path": [
      0,
      4
    ],
    "node": {
      "type": "mapped-field",
      "value": "166003157__hello",
      "children": [
        {
          "text": ""
        }
      ]
    }
  },
  {
    "type": "insert_text",
    "path": [
      0,
      3
    ],
    "offset": 0,
    "text": "{{166003157__hello}}"
  },
  {
    "type": "set_selection",
    "properties": {
      "anchor": {
        "path": [
          0,
          2
        ],
        "offset": 0
      },
      "focus": {
        "path": [
          0,
          2
        ],
        "offset": 0
      }
    },
    "newProperties": {
      "anchor": {
        "path": [
          0,
          3
        ],
        "offset": 20
      },
      "focus": {
        "path": [
          0,
          3
        ],
        "offset": 20
      }
    }
  },
  {
    "type": "remove_node",
    "path": [
      0,
      2
    ],
    "node": {
      "text": ""
    }
  },
  {
    "type": "remove_node",
    "path": [
      0,
      1
    ],
    "node": {
      "type": "mapped-field",
      "value": "166003157__id",
      "children": [
        {
          "text": ""
        }
      ]
    }
  },
  {
    "type": "merge_node",
    "path": [
      0,
      1
    ],
    "position": 12,
    "properties": {}
  },
  {
    "type": "insert_text",
    "path": [
      0,
      0
    ],
    "offset": 12,
    "text": "{{166003157__id}}"
  },
  {
    "type": "remove_text",
    "path": [
      0,
      0
    ],
    "offset": 0,
    "text": "sdfsdfsdfsdf{{166003157__id}}{{166003157__hello}}"
  }
]
Read more comments on GitHub >

github_iconTop Results From Across the Web

Slate.js throws an error when inserting a new node at selected ...
I think your issue stems from the fact that <Slate> is the context provider, and you should actually be using a nested <Editable>...
Read more >
CodeMirror 5 User Manual
CodeMirror is a code-editor component that can be embedded in Web pages. ... The distribution comes with a number of modes (see the...
Read more >
48 answers on StackOverflow to the most popular Angular ...
I gathered the most common questions and answers from Stackoverflow. These questions were chosen by the highest score received. Whether you are an...
Read more >
Node — Godot Engine (stable) documentation in English
See _ready. ... Finds a descendant of this node whose name matches mask as in ... If the path does not exist, null...
Read more >
.contents() | jQuery API Documentation
contents()Returns: jQuery. Description: Get the children of each element in the set of matched elements, including text and comment nodes. version ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found