Bug: button onFocus not called when focus() called from useEffect cleanup
See original GitHub issueReact version: 16.12.0
Steps To Reproduce
- Have a
<button/>
HTML element withonFocus
event handler defined
<button ref={btnRef} onFocus={() => console.log("I'm in focus")}>Focus Target</button>
- Have another component with
useEffect
cleanup code which will callfocus()
React.useEffect(() => {
const ref = btnRef.current; // btnRef is a ref to the button component above
return () => {
console.log("effect cleanup ", new Date().toISOString());
ref.focus();
};
}, []);
When the cleanup code from useEffect
is called, onFocus
event handler of the button
is not called. The button
is rendered in a component which is mounted when useEffect
cleanup executes. For example it can be in the parent component.
Link to code example: https://codesandbox.io/s/onfocus-not-called-from-useeffect-cleanup-npw7k
- Open example in browser (tested in Chrome 79.0.3945.88 and in Firefox 72.0.1).
- Open dev console
- Click on Focus target button. See another component below it with two buttons.
- Remove focus from Focus target button by setting it in adjacent input field
- Click on Set focus button. Observe that focus is set to Focus target button and in console see message ‘I’m in focus…’. This message is logged from
onFocus
event handler - Remove focus from Focus target button.
- Click Close me button. Observe that focus is set to Focus target button but no message in console from
onFocus
event handler
The current behavior
onFocus
is not called
The expected behavior
onFocus
is called
Issue Analytics
- State:
- Created 4 years ago
- Reactions:8
- Comments:7 (2 by maintainers)
Top Results From Across the Web
Controlling Input Field Focus With React State and UseEffect
I want to be able to use the button to toggle focus on and off at my choosing. The only thing not working...
Read more >useFocusEffect - React Navigation
The useFocusEffect allows you to run an effect on focus and clean it up when the screen becomes unfocused. It also handles cleanup...
Read more >Understanding React's useEffect cleanup function
Learn React's useEffect cleanup function to prevent unwanted application behaviors like memory leaks by cleaning up effects.
Read more >React v17.0 Release Candidate: No New Features
The solution is to capture any mutable values inside the effect: useEffect(() => { const instance = someRef.
Read more >How To Handle DOM and Window Events with React
Then you added a button called Save directly before the closing ... As mentioned earlier, the event here is not the native browser...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Hey all,
I think I have stumbled on the same bug but also discovered another weird behaviour in relation to this. Both issues I’m seeing here (the event one already mentioned, + the new one) appear to have been fixed in v17. That said, I thought I’d report it anyway because of the second behavior I saw, as I don’t know if the react team is aware.
I have setup a sandbox to demonstrate the issue.
onFocusCapture
listener.focus
listener (capture phase too) on the document.latest stable react 16.13.1
https://codesandbox.io/s/react-unmount-focus-bug-0qn8q
Here’s what we can observe:
onFocusCapture
event was never called (same issue as discussed in this thread I think), we only see the native one.react 17.0.0-rc.3
Here is the exact same sandbox, but with react updated to v17, you can see both issues seem to be resolved:
https://codesandbox.io/s/react-unmount-focus-bug-fixed-in-v17-t7zcw
Let me know if that weird re-focusing behavior was known or not. Happy to see if fixed in 17 but wasn’t sure if it was accidental like @gaearon mentioned.
✌️
It also seems that this is only broken when the effect is unmounting, but works fine when it is updating:
In this example the input isn’t even focused at all, but if you change
key={state}
tok={state}
it works fine, although there is seemingly no reason for such a discrepancy.It goes without saying that adding
setTimeout(0)
fixes things.