Skip to content
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

Dispatching at the same time as setState causes two renderings #1912

Open
1 task done
mineoka-kento opened this issue Apr 22, 2022 · 9 comments
Open
1 task done

Dispatching at the same time as setState causes two renderings #1912

mineoka-kento opened this issue Apr 22, 2022 · 9 comments

Comments

@mineoka-kento
Copy link

mineoka-kento commented Apr 22, 2022

What version of React, ReactDOM/React Native, Redux, and React Redux are you using?

  • React: 18.0.0
  • ReactDOM:18.0.0
  • Redux Toolkit:1.8.1
  • React Redux:8.0.1

What is the current behavior?

Synchronous calls to dispatch and setState within useEffect will cause separate re-rendering.

Since it may not be possible to check visually, try using the Profiler in the React Developer Tools to see how it works.

https://codesandbox.io/s/brave-dew-cc7p4p?file=/src/features/counter/CounterEditor.tsx

screen-recording_1

What is the expected behavior?

The re-rendering occurs only once.

Which browser and OS are affected by this issue?

Chrome/100.0.4896.127, Windows10

Did this work in previous versions of React Redux?

  • Yes
@mineoka-kento
Copy link
Author

Since the video was difficult to understand, I upload the original video file.
screen-recording.zip

@markerikson
Copy link
Contributor

Without having fully investigated yet: batching and render timing are owned by React, not React-Redux. We don't have full control over that.

I would have expected that all updates queued in a useEffect would be batched together, especially under React 18. But, the nuances of this one are tricky.

Either way I don't think there's anything we can specifically do here, and I don't think this is actually a "bug".

@HelloWorld017
Copy link

The OP has used React.StrictMode , so I have suspected that makes useEffect run twice.

But, unfortunately, I could made another repro for this issue, without StrictMode.
This should run ok with react-redux@7 + react@18, but if you run this with react-redux@8 + react@18, it throws an error, Maximum update depth exceeded.

Actually, the example I have made can be fixed, if you use dependencies for the useEffect.
But this example shows that if you call setState and dispatch, a rerender, with updates from dispatch and without updates from setState, can happen even if you call setState prior to the dispatch.

@timdorr
Copy link
Member

timdorr commented Aug 12, 2022

Yes, it's actually that. Good call!

@timdorr timdorr closed this as completed Aug 12, 2022
@phryneas
Copy link
Member

Isn't that still a problem that we should maybe bring up with the React team?
I mean, that problem essentially occurs because state updates happen out of order - the later Redux update happens before the earlier state setter call.
That essentially means that Redux updates break out of the automated batching here, which was not a problem before when react-redux used setState to trigger a rerender.

@markerikson
Copy link
Contributor

Andarist pointed out this is likely the same thing as facebook/react#24831

@MrBr
Copy link

MrBr commented Oct 2, 2022

It seems like problem is more complex than just rendering twice.

Dispatching redux action in the same effect where a local state is updated cancels the local state update.

I've created a codesandbox with a simple to reproduce example.

https://codesandbox.io/s/friendly-worker-fdyvqk

Probably it's on React side as mentioned but posting here maybe it will be helpful.

@phryneas
Copy link
Member

phryneas commented Oct 2, 2022

This will be changed on the React side - unfortunately at this point there's not really anything we can do about it: facebook/react#25191 (comment)

@markerikson
Copy link
Contributor

Update: this is hopefully fixed in React 19:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants