rerender slate when focus changes. #3988
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Rerender slate when focus changes. Fixes #3987
Is this adding or improving a feature or fixing a bug?
Fixing a bug
What's the new behavior?
I've shown the old behavior in the initial bug report. When the editor loses focus due to the user pressing tab or escape the
useFocused
hook does not update. While debugging I found that this is due to theSlate
wrapper not rerendering, so theuseFocused
Context Provider never receives a new value.Here is a code snippet which can be used to demonstrate the new behavior. Without the new code
is focused
only logs when you click outside the editor. With the new behavioris focused
logs when you tab outside of the editor or press escape.How does this change work?
When looking at the code I realized
ReactEditor.isFocused
does return the correct value at all time already.Blur
andFocus
events are already getting handled correctly. The only issue isSlate
is not rendering when theReactEditor.isFocused
value changes.In order to resolve the issue I just need to get slate to rerender when focus changes. My solution is in
slate.tsx
. In my solution I moveisFocused
to local react state. I listen tofocus
andblur
events at the document level and then update the local state withReactEditor.isFocused
. I also update the local state on every render withuseEffect
. You can see this implementation inslate.tsx
.If
useState
returns the same value as the previous state then react will not rerender. So this code should not cause any unnecessary renders.Have you checked that...?
I wanted to try and avoid the
focus
andblur
handlers ineditable
because there is a bunch of edge case behavior handled there. All of those edge cases should still be handled the exact same way, because my change is essentially a read only change to readReactEditor.isFocused
when the focus changes on the page.yarn test
.yarn lint
. (Fix errors withyarn fix
.)yarn start
.)Does this fix any issues or need any specific reviewers?
Fixes: #3987
Reviewers: