-
Notifications
You must be signed in to change notification settings - Fork 46.9k
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
Bug: Click event using window.addEventListener is fired prematurely #24657
Comments
This looks like the expected behavior, synchronously registered event handlers are called at initialization, look at this example, |
This is related to #21150 in React 18, the effects resulted from onClick are flushed synchronously. |
The behavior in 17 was inconsistent. Here's an example using 17 but the event does get handled synchronously: https://codesandbox.io/s/runtime-glitter-256mit?file=/src/App.js The only difference is that I added rendering of a portal. This issue was originally described in #20074. In 18, the behavior is consistent. Effects caused by a render from an intentional user event like clicking/typing are always flushed synchronously. So you'd need to tweak the logic of the modal but at least it will always work the same way. One possible workaround is to delay the subscription with a zero timeout. Another possible workaround is to capture the current event during the effect and ignore that particular event in the handlers (like in microsoft/fluentui#18323). |
Beautiful, thank you! |
Maybe I'm missing something but wouldn't it be better to stop event propagation before we show the dialog? (Not my idea) |
I'm curious why |
React version:
Steps To Reproduce
Link to code example:
react@next react-dom@next
to verify that the latest (unreleased) version doesn't work either.The current behavior
If you open the React 18 CodeSandbox link from above, what you will notice when you hit the
Open Dialog
button is that you will receive an event likeGot event in <Dialog />!
I tried to minimize the reproduction, the idea is that we have a
Dialog
component that receives anopen
prop, based on this prop we know to show theDialog
or not. However aDialog
should also have "outside click" behaviour, to fake this I setup awindow.addEventListener('click')
inside a useEffect to "capture" this behaviour. However when I click theOpen Dialog
button this is what happens:Open Dialog
open
state totrue
open={true}
to theDialog
componentwindow.addEventListener('click')
if theopen
value is trueclick
event from step 1.Console logs after clicking once on the
Open Dialog
button:The expected behavior
If you open the React 17 CodeSandbox and repeat those steps from above, then you will see the expected behaviour where clicking on the
Open Dialog
does not trigger the log from within thewindow.addEventListener('click')
it's only the second time that you click that button that it will log something because now theDialog
is considered in anopen
state.Console logs after clicking once on the
Open Dialog
button:Is this a bug, a regression or am I doing something incorrect here? I'm confused how a
window.addEventListener
can receive an event from a click that happened before the listener was even setup 🤔The text was updated successfully, but these errors were encountered: