🐛 Fix #5084: Fixfox Tab switch issue #35
Open
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.
Close Hacker0x01#5084
Description
As @avazhenin mentioned in the attached ticket, we're getting an issue while we try to switch to the next input control via Tab Key on Firefox browser.
To Reproduce
Even though @avazhenin shared his code sample along with a video explaining the issue, I'll share a simple way to recreate the issue. Goto
https://reactdatepicker.com/
via FireFox and click on any date input, now try to press tab when the calendar is getting rendered. We expect it to auto-close the calendar and switch to the next code sample. But instead of that it'll refocus the same date input again. To make it work, we have to press ESC first (which will close the opened calendar popup) and then press Tab, it'll work. In this case alone it'll work, because as the datepicker is already closed, it won't disturb the tab key press.Try the same thing in Chrome Browser, it'll auto-close the opened calendar popup and switch to the next code sample editor.
Reason behind this issue
The reason why this issue occurs whenever we press Tab key over the input, we call
setOpen(false)
to close the open popup so that the browser default focus switch will happen to the next control.But as I highlighted in the above screenshot, while performing the state update we manually call blur operation on the date input. We do a state update and along with setting blur to the DOM element. This issue arises from a combination of
1. JavaScript Event Loop & React's Rendering Lifecycle:
setState
assuming the blur will happen after the update of state. But React's state updates are asynchronous and may not complete immediately aftersetState()
. The callback of setState runs after the state update, but not guarantee that the DOM has been fully updated and rendered (unlike theuseEffect
call).2. Browser-Specific Focus Behaviour:
blur()
call made by us in-between the state update.Changes/Solution
Wrapping the blur() call inside a setTimeout defers it to the next macrotask, ensuring that React's render and browser focus management complete before the blur operation is executed.
As we wrapped
setBlut
call inside the setTimeout, we need to move the focus logic also to setTimeout, as in the case of Esc key press we kind of blur and send focus back to the input. So in this PR I moved the focus and blur call inside setTimeout.I created 2 new methods and moved our existing blur and focus call to it instead of updating the existing methods names. Updating the existing method names make me update many lines as these functions are used in many places. So to keep my fix simple and at the same time to emphasize the change I made, I created these 2 new helpers.
I updated the existing test cases to adapt with my fix and also added a new test case to check the Tab order.
Contribution checklist