slate: Focus breaks when calling setState in onFocus / onBlur
Do you want to request a feature or report a bug?
bug
What’s the current behavior?
When you call setState()
from within an onFocus()
or onBlur()
handler the editor can no longer receive / release focus. Here is a JSFiddle illustrating the problem: https://jsfiddle.net/fj9dvhom/2611/. Just try to focus or unfocus the editor.
Chrome: Version 70.0.3538.102 (Official Build) (64-bit) Mac OS: 10.14.1
What’s the expected behavior?
Focusing should work correctly.
I have a suspicion that the setState()
call is causing a render event before the editor can finish handling the original focus / blur event. Wrapping the setState()
in a setTimeout()
seems to alleviate the issue.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 15
- Comments: 19 (10 by maintainers)
#2451 is a different issue, this bug occurs even with one editor. For some reason
setTimeout
fixes blurring:which imho this is the proof that it is a race condition issue.
See online demo: https://jsfiddle.net/fj9dvhom/2734/
Yes, this one needs to be fixed on priority as it’s totally a blocker. It took my 2 days to figure out why my editor was not working, as it doesn’t even throw any error.
I’m quite surprised to find that
setState()
on a parent’sonBlur/Focus
handler also prevents the editor from gaining/losing focus. I’d expectEditor
’s inner workings to be immune from external state changes like this?I’ve forked @ericedem’s fiddle, and simply moved the
onFocus/Blur
handler to a<div>
wrapper to demonstrate the problem here: https://jsfiddle.net/thatmarvin/sLkq06yt/Wrapping
setTimeout
also fixes the problem: https://jsfiddle.net/thatmarvin/fa0encyd/I finally figure out how to avoid editor losing focus. My solution is based on @steida recommandation of tracking
isFocused
. Here is what I did:That trick means that you will block
onBlur()
event handling for all other plugins until the next react render cycle, which could result in some pretty unexpected behavior. Especially since slate is expecting to call all the event handlers synchronously.The better workaround is to track selection.isFocused changes and never ever use onFocus nor onBlur imho.
@ericedem Thanks Eric, I’m pretty new to both slate and React, so thanks for the advice. Will go with the setTimeout workaround for now.
Sorry, the one I posted in #2451