-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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
Dispatch more than once in non-batched update cause incorrect result with useSelector
#1437
Comments
I'v created a PR #1438 and it seems fixed the issue. |
Per my comment in the PR, that change is not correct. Can you clarify what "incorrect value" you're seeing here? |
Looking at your code example, I'm not convinced that you're seeing buggy behavior. There are multiple complex aspects for how batching behaves. If you can provide some specific details on what you are expecting to see, and what is happening, it would help me understand what's going on. |
I implement the same demo in web. https://codesandbox.io/s/silly-browser-h5z4z As you can see after button clicked, |
So, yes, useSelector provides state from the store at different times than when it exists within the store. This is unavoidable, because React behaves in a semi-asynchronous manner right now (i.e., setState is not synchronous) and will be even more async-y with Concurrent Mode. However, I don't classify this as a bug. It's just a behavior of the library. We conform to React's update process so that we can achieve reasonable performance. This may create point-in-time inconsistencies between different APIs to access state, but I would posit that you are also using those APIs inconsistently by mixing and matching them in the same context (a React component). If you're wanting to use useSelector, you should only use that, so the results are consistent. Going around it and accessing state directly isn't expected and advised, so this isn't something we're going to fix or change. |
I am curious what's going on if there are truly differences in behavior between native and web. |
@timdorr I think you closed the issue too early. I advice you to try the React Native demo even it may cost you some minutes to make environment ready. I don not intentionally use In react-dom demo https://codesandbox.io/s/silly-browser-h5z4z But in react-natove demo https://github.com/malash/react-redux-issue-ref I believe the GIF does show how the boolean changed. @markerikson I agree with your comment in #1438 . I guess if react-redux still use |
@timdorr @markerikson Could you please revisit this issue ? There must be some bugs in |
@malash : I'm not going to say that React-Redux is perfect, but no, I don't see evidence here that things are buggy with React-Redux itself. If you can dig into this further and provide more evidence that something may be going wrong, we can take another look. In particular, I would suggest trying to add some kind of logging to RN's batching implementation and see if it's being hit properly. |
Hey @markerikson @timdorr We believe this is still an issue with We need useLayoutEffect to ensure the store subscription callback always has the selector from the latest render commit available, otherwise a store update may happen between render and the effect, which may cause missed updates You use We think this is a still an issue, and I would propose we find a better gating for node environment than using |
@MingruiZhang : I'm not sure what problem you're trying to point to here, or how the referenced lines relate. Can you clarify? While I haven't used RN, this post seems to suggest that https://stackoverflow.com/questions/49911424/what-does-the-variable-window-represent-in-react-native |
It's possible that RN has window, but I don't think it has
The main issue here is that we have 2 Now the second one listens to In the given scenario, 2 sequential dispatch takes place (we used setTimeout to prevent it getting batched).
Dispatch1 useIsomorphicLayoutEffect#2 -> Dispatch1 render -> Dispatch1 useIsomorphicLayoutEffect#1 -> Dispatch2 useIsomorphicLayoutEffect#2 -> Dispatch2 render -> Dispatch2 useIsomorphicLayoutEffect#1.
Dispatch1 useIsomorphicLayoutEffect#2 -> Dispatch1 render -> Dispatch2 useIsomorphicLayoutEffect#2 -> Dispatch1 useIsomorphicLayoutEffect#1 -> Dispatch2 render -> Dispatch2 useIsomorphicLayoutEffect#1. Noticed that because @markerikson does this makes sense to you? Any sequential updates from non-web platforms will suffer from this issue, and it would be really helpful if we can get a fix here. |
Hmm. Okay, yeah, if that's the case, I can see how this would be a problem. So... is there a better solution for detecting Node vs RN vs web? This SO answer suggests checking https://stackoverflow.com/questions/39468022/how-do-i-know-if-my-code-is-running-as-react-native |
@MingruiZhang react-redux/src/hooks/useSelector.js Lines 15 to 16 in 91116ac
seems to solve the issue. Correct? |
The additional checks were added as part of #1283 , to keep the SSR warning from happening if Ironically, someone actually warned about the RN issues here: I would like us to make a few changes as part of fixing this:
|
Thanks for the clarification! facebook/react#14927 (comment)
Totally agreed with this. A crazy idea: Can we simply tolerate the warning? Mitigation with docs? |
@markerikson Appreciate reopening this issue! I want to point out that we found this issue while we work on building WeChat Miniapp, with our own react renderer, we fall into the same situation as RN not having I totally agree that maybe React shouldn't throw these warnings in the first place, but I guess that's not to our hands to decide. Few other thoughts I have here
|
The problem is we also rely on this same And I'd really rather not have the SSR warnings be a thing again either. |
@markerikson I totally agree with you. I think it's not ideal as well. I'm also a bit confused on the whole logic inside |
I think I've got a fix in place for this, and some unit tests to match. I'm going to publish a test version shortly and will let you know when it's up. |
Just published |
We ran into this issue today and the |
Do you want to request a feature or report a bug?
Report a bug.
What is the current behavior?
I'v created a reproducing repo here https://github.com/malash/react-redux-issue-ref/blob/master/reduxBug.js
This repo use both
react-redux
andreact-native
.When using
setTimeout
's callback to dispatch multi times, theuseSelector
return incorrect value. The reason why I usesetTimeout
is to ensure these dispatch calling are non-batched.After click the button different selector result are shown. the
bool
are always different withboolFromStore
.If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to a CodeSandbox (https://codesandbox.io/s/new) or RN Snack (https://snack.expo.io/) example below:
react-native run-ios
What is the expected behavior?
This bug can only reproduce on non-web environment, maybe it is related to #1436
I believe it should works on React Native as well as React DOM.
Which versions of React, ReactDOM/React Native, Redux, and React Redux are you using? Which browser and OS are affected by this issue? Did this work in previous versions of React Redux?
react@16.9.0
react-native@0.61.2
react-redux@7.1.1
redux@4.0.4
cc
@byunicorn
The text was updated successfully, but these errors were encountered: