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

multiple `setState` calls in async callbacks trigger multilple updates #16377

Closed
wangcheng678 opened this issue Aug 13, 2019 · 12 comments

Comments

@wangcheng678
Copy link

commented Aug 13, 2019

Do you want to request a feature or report a bug?

bug

What is the current behavior?

When using usingState hook, mutiple setState calls in async callbacks will trigger multiple updates and useEffects.

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 your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

https://codesandbox.io/s/react-async-set-state-bug-zsztm

Click 'sync' button, countA and countB will be updated at the same time. The useEffect will run only ONCE with the updated countA and countB.

Click 'async' button, countA and countB will be updated in sequence. The useEffect will run TWICE with the updated countA and old countB at the first time and both updated values at the second time.

What is the expected behavior?

The two setStates should only triger one update.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

16.9.0

@kunukn

This comment has been minimized.

Copy link
Contributor

commented Aug 13, 2019

related topic
#14259

You can use ReactDOM.unstable_batchedUpdates to ensure batched update.
https://codesandbox.io/s/react-async-set-state-bug-7jcgx

@miraage

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2019

By "update", do you mean render call or the state update itself? I clicked all three buttons many times, got both A & B to 100+ and their values were equal.

@kunukn

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2019

If you inspect the console and compare the two codesandbox examples you should see a difference.

By update I mean how many times the useEffect is called.

The usage of ReactDOM.unstable_batchedUpdates solves the expected behaviour.

What is the expected behavior?
The two setStates should only trigger one update.

@wangcheng678

This comment has been minimized.

Copy link
Author

commented Aug 14, 2019

@kunukn So you mean I should not assume that multiple setState will or will not be batched into a single update?

@miraage

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2019

@wangcheng678 could you please show a link to the documentation where it says that multiple setState calls will result to a single update?

@wangcheng678

This comment has been minimized.

Copy link
Author

commented Aug 14, 2019

@miraage My point is the behavior is different in sync and async callbacks.

@miraage

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2019

@wangcheng678

  • this doc is for class components, not hooks
  • I can't remember a React version where class component setState guaranteed multiple setState calls resulting in a single update
@TroyTae

This comment has been minimized.

Copy link

commented Aug 14, 2019

@miraage
I remember that React.js guaranteed single update.
(https://twitter.com/dan_abramov/status/824309659775467527)
Maybe they're using mechanism of event loop 🤔

@miraage

This comment has been minimized.

Copy link
Contributor

commented Aug 14, 2019

@TroyTae please read the tweet itself:

It is safe to call setState with a function multiple times. Updates will be queued and later executed in the order they were called.

It means that setState(stateUpdaterFunction) is safe to be enqueued and the order will be guaranteed (order of applying the state updater functions), but setState(partialStateObject) order is not guaranteed.

@TroyTae

This comment has been minimized.

Copy link

commented Aug 14, 2019

@miraage
Oh I have misread this issue.
Of course setState is executed multiple times, but I want to say render-update is fired single time!
I'll split my issue as a new one :)

@miraage

This comment has been minimized.

Copy link
Contributor

commented Aug 15, 2019

@gaearon

This comment has been minimized.

Copy link
Member

commented Aug 15, 2019

#16387 (comment)

(Btw this is how it always worked, and is unrelated to Hooks)

@gaearon gaearon closed this Aug 15, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.