Skip to content

fix(slate-react): prevent useSelected from throwing when element is removed#6073

Open
NikunjSonigara wants to merge 2 commits into
ianstormtaylor:mainfrom
NikunjSonigara:fix-useSelected-remove-self-6053
Open

fix(slate-react): prevent useSelected from throwing when element is removed#6073
NikunjSonigara wants to merge 2 commits into
ianstormtaylor:mainfrom
NikunjSonigara:fix-useSelected-remove-self-6053

Conversation

@NikunjSonigara

Copy link
Copy Markdown

Fixes

Fixes #6053

Summary

This PR prevents useSelected from throwing when the referenced element has been removed from the editor while still being referenced by a mounted React component.

Previously, when an element was deleted, ReactEditor.findPath or Editor.range could throw:

Cannot find a descendant at path [...]

This would cause runtime crashes in components still holding a reference to the removed element.

Solution

The path resolution and range calculation are now wrapped in a try/catch. If the element can no longer be resolved (because it has been removed from the editor tree), useSelected safely returns false instead of throwing.

Why this works

When the element is removed, it is no longer part of the editor's document tree, so selection state should be treated as false rather than attempting to compute a range on a non-existent node.

Test coverage

A regression test was added to ensure:

  • A component still referencing a removed element does not crash
  • useSelected() returns false after the element is removed
  • Behavior is consistent with and without chunking enabled

Notes

This fixes a real-world crash scenario where stale element references exist during React render cycles after DOM updates in Slate.

@changeset-bot

changeset-bot Bot commented Jun 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 2840d76

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
slate-react Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@dylans dylans left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general pattern we have been using to stop throwing is to make this opt-in. Some people prefer that things throw rather than failing silently. There are a few recent PRs that have made error throwing configurable, so I would prefer that approach. For example #6072.

Also there are a lot of comments in here that I would consider to be over-explaining by AI, please clean those up.

…Throw

Address review feedback on ianstormtaylor#6073: instead of silently swallowing the
error, add an opt-in `suppressThrow` option to `useSelected` so the hook
keeps throwing by default and callers opt in to returning `false` when
the element can no longer be resolved. Follows the `suppressThrow`
pattern from ianstormtaylor#6072. Also trim the explanatory comments.
@NikunjSonigara NikunjSonigara requested a review from dylans July 1, 2026 14:46
@NikunjSonigara

Copy link
Copy Markdown
Author

Thanks for the review @dylans, I have updated the PR:

  • Made it opt-in instead of silently swallowing. useSelected now accepts a suppressThrow option and throws by default (unchanged behavior). Callers opt in with useSelected({ suppressThrow: true }) to get false when the element can no longer be resolved. This follows the suppressThrow pattern from fix(slate-dom): propagate suppressThrow to toSlateNode in toSlatePoint #6072
  • Cleaned up the comments - removed the over-explaining ones in both the hook and the test

Since the default still throws, users hitting #6053 opt in via useSelected({ suppressThrow: true }). Happy to adjust the option name or default if you'd prefer something different.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

useSelected error when remove myself

2 participants