-
Notifications
You must be signed in to change notification settings - Fork 47.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
React 18 different behavior of ReactDom.createRoot and ReactDom.render #23097
Comments
The repro above could be simplified a lot, but it's demonstrating a similar pattern as I remember accounting for in DevTools some time ago (#21173). This is the solution I went with at the time: react/packages/react-devtools-shared/src/devtools/views/hooks.js Lines 233 to 247 in 9a7e6bf
Although I also wrote about a few alternative solutions here, if you are interested: The main issue at hand here is that React synchronously runs effects (including passive effects) inside of events like "click" events. (Note that this behavior was always possible, if a layout effect scheduled a state update– which had to be processed synchronously– then passive effects would be flushed in between.) The decision was made by the React team to reduce the complexity of imperative code (in effects) by making their behavior more consistent and predictable. I think this makes things simpler in the common case, although it can lead to some awkward edge cases like the one we're discussing. cc @gaearon @sebmarkbage in case you're aware of additional context or if I'm misremember anything. |
Thank you @bvaughn for a quick reply and your examples. I came up with a solution of wrapping it inside setTimeout but was not quite sure if that was a correct way of solving the problem. But the trick with performance looks really neat. I should definetly add it to my tool belt. |
React 18.0.0-rc.0
I noticed a different behavior when using new ReactDom.createRoot feature comapared to the current ReactDom.render
So I have this demo project here to illustrate the problem.
The setup is pretty simple. The app component has a boolean state to open/close modal. The modal component calls a custom hook useOutsideClick whick adds a click event listener to the window and calls a callback passed to that hook if the click was triggered outside the ref element which is passed as arguments to that hook.
When I use the current ReactDom.render everything works fine as expected. You click the button, the modal opens, the window click event is added, then you click outside the ref object, the modal is closed. But when I switch to new ReactDom.createRoot which is reccomended when using React 18, I get a different behavior. When I click the button to open a modal, the addEventListener inside useEffect in useOutsideClick is called during the bubbling phase, the modal is mounted, then the click event bubbles up to the window which now has a click event registered, and as the click happened on the button which is outside ref object the modal is closed.
I am not really sure if that new behavior is a bug or a feature but I at least would like to hear some explanation on that.
In indes.tsx file I left the code for createRoot commented out so you could easily switch between these two apis.
The text was updated successfully, but these errors were encountered: