React 18 StrictMode
See original GitHub issueHey! I’m having an issue opening my custom modal with FocusTrap in StrictMode after upgrading to React 18. When the modal state is opened onDeactive
is called immediately (probably because of the double render in Strictmode), which closes the dialog.
I see you have recently released a fix for StrictMode but it doesn’t fix this issue.
I made a demo where i just copied the example from: demo/js/demo-special-element.js
The change i made in the demo is to only render the FocusTrap element when it is active.
Code sandbox demo: https://codesandbox.io/s/0vhfsb
Is this a bug or should i implement it differently?
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:7 (7 by maintainers)
Top Results From Across the Web
Strict Mode
StrictMode is a tool for highlighting potential problems in an application. Like Fragment , StrictMode does not render any visible UI. It activates...
Read more >Using strict mode in React 18: A guide to its new behaviors
React v18 introduced new strict mode behavior regarding unmounting and remounting. Now, each element will be unmounted and remounted with the ...
Read more >How to use React Strict Mode in React 18
React Strict Mode is a developer tool highlighting potential bugs or issues in a React application's codebase. It provides warnings to ...
Read more >Does strict mode work differently with React 18?
In React 18, StrictMode gets an additional behavior to ensure it's compatible with reusable state. When Strict Mode is enabled, React ...
Read more >React
If your app doesn't work after upgrading to React 18, the first thing to check is whether it's wrapped in <StrictMode>. Strict Mode...
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 FreeTop 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
Top GitHub Comments
@lasseklovstad I had a closer look. Turns out, AFAICT, the trap is doing what it’s supposed to do, especially after #721, which is to handle being immediately unmounted and remounted after being initially mounted (behavior caused by Strict Mode).
This works for the use case in #721 when you don’t have a component outside the
<FocusTrap>
that is controlling the trap’s active state. A trap is active by default, so if you just plop one down and render, under Strict Mode, the fix in #721 is employed to restore the trap to an active state in the remount.But in your case, because you have this
activeTrap
state variable, and you have this method tied to the trap’sonPostDeactivate
event:thing don’t work so well because, under Strict Mode, the trap gets unmounted – which causes this handler to get called, thus setting activeTrap to false. Then the trap is remounted, but then there’s an immediate React state update (because the outer component’s
activeTrap
state changed from true to false), and since you’re conditionally rendering the trap whenactiveTrap
is true, the trap gets unmounted again, the handler gets called again (has no effect this time since the state is already false), and things settle.And you’re left with no visible trap.
So this isn’t a bug with the trap. Of course, not using Strict Mode, it works just right. The trap renders when
activeTrap
becomes true, and it’s active.I’m not sure what to suggest here. As you know, I’m not a fan of this behavior of Strict Mode. There are other things Strict Mode which I’m fine with. But this unmount/remount thing, no. IMO, React has an idea of what they want to do in the future (i.e. temporarily/dynamically disabling parts of the UI by unmounting them, and then reactivate them later by remounting them), but this behavior violates their API (as I explained in #720). And focus trap is behaving correctly according to the API. 🤷♂️ Not sure how to reconcile that, short of being able to somehow detect strict mode, and have the trap behave differently in that case (i.e. by expecting an initial unmount and setting a flag to remember it has happened, and not deactivating the trap, avoiding triggering the deactivation event handlers, that one time), something I’m also not a fan of.
@Slapbox
I don’t know of any way to detect strict mode, and I’m guessing that would be beside the point of strict mode. I also don’t think it’s good to have a version of the component that works in strict mode one way, and another version that works in not strict mode another way… I really loathe strict mode for this.
What in 10 made this impossible? The only thing that changed in 10 was the tabbable dependency, and there’s a workaround to restore the old behavior. There were no code changes in 10 at all. Functionally, aside from the need for the workaround for old behavior (if it’s even an issue), the library is the same as it was in 9.0.2