Child may render with new state before parent
See original GitHub issueWhat is the current behavior?
Full reduced test case: https://github.com/OliverJAsh/react-redux-and-context-renders-test
Same reduced test case in the form of a StackBlitz: https://stackblitz.com/edit/react-redux-and-context-renders-test?file=index.tsx
The example might look contrived but it’s based on real world code that is in production on Unsplash. Apologies in advance that I couldn’t provide a simpler example—this is the smallest reduced test case I was able to find.
The simplified component tree looks something like this:
GridWrapper
Grid
Item
The child component Item
is rendered with new Redux state (windowWidth
) before its parent, Grid
. We can see this from the logs I added to component render functions:
What I expect: the child component Item
should not be rendered with the new Redux state before its parent, Grid
.
The issue seems to occur when React re-renders due to simultaneous changes to context and Redux state.
From my understanding, this is what’s happening:
Item
is subscribed to both the context value and Redux state.- After the first render, we simultaneously update the context value and Redux state. React will batch these renders because they are triggered by lifecycle methods (
componentDidMount
). - React Redux will re-render
GridWrapper
with the new state. At the same time, React will re-render context consumers with the new context value.Item
is inside of a context consumer so it will re-render, but incidentally this will also mean it will use the new Redux state, even though React Redux hasn’t told it to. - Finally, React Redux will re-render
Grid
with the new state.
As I understand it, the only way to avoid this problem would be to fix https://github.com/reduxjs/react-redux/issues/1510 so that nested updates at different levels are batched.
What is the expected behavior?
See above.
Which versions of React, ReactDOM/React Native, Redux, and React Redux are you using?
The latest versions of everything, at the time of writing.
"dependencies": {
"react": "16.13.1",
"react-dom": "16.13.1",
"react-redux": "7.2.0",
"redux": "4.0.5",
"typescript": "3.9.3"
},
Which browser and OS are affected by this issue?
All.
Did this work in previous versions of React Redux?
I’m not sure.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:9 (8 by maintainers)
Top GitHub Comments
For now we were able to workaround this by moving the React Redux
connect
to live outside of the context consumer.Before:
After:
This way, when the context consumer is re-rendered due to context changes, the previous connected props will be re-used.
https://stackblitz.com/edit/react-redux-and-context-renders-test-hvhqwv?file=index.tsx
This works for class component. How would one fix it when using functional components?