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
wangcheng opened this issue Aug 13, 2019 · 12 comments
Closed

multiple setState calls in async callbacks trigger multilple updates #16377

wangcheng opened this issue Aug 13, 2019 · 12 comments

Comments

@wangcheng
Copy link

wangcheng 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
Copy link
Contributor

kunukn 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
Copy link

miraage 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
Copy link
Contributor

kunukn 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.

@wangcheng
Copy link
Author

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

@miraage
Copy link

miraage 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?

@wangcheng
Copy link
Author

wangcheng commented Aug 14, 2019

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

@miraage
Copy link

miraage 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

@ghost
Copy link

ghost 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
Copy link

miraage 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.

@ghost
Copy link

ghost 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
Copy link

miraage commented Aug 15, 2019

@wangcheng678 #16387 (comment)

@gaearon
Copy link
Collaborator

gaearon commented Aug 15, 2019

#16387 (comment)

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

@gaearon gaearon closed this as completed Aug 15, 2019
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

4 participants