Right, there can be an issue with state setting not happening in sequence, and sometimes being combined. As I understand React … If I do: this.setState({ foo: 1 }); this.setState({ foo: 1 }); this.setState({ foo: 1 }); this.setState({ foo: 1 }); this.setState({ foo: 1 }); There is no guarantee w… Answer from kevinSmith on forum.freecodecamp.org
🌐
freeCodeCamp
forum.freecodecamp.org › curriculum help
React: Why pass in setState(), a function instead of an object - Curriculum Help - The freeCodeCamp Forum
June 5, 2021 - And it’s because sometimes setState() calls are batched and run asynchronously and if at the time of updating the state, you need the previous state, you can’t rely on the current state value though.
🌐
Medium
medium.com › @wisecobbler › using-a-function-in-setstate-instead-of-an-object-1f5cfd6e55d1
Using a function in `setState` instead of an object | by Sophia Shoemaker | Medium
February 6, 2018 - Normally, when we want to update our component we just call setState with a new value by passing in an object to the setState function: this.setState({someField:someValue}) But, often there is a need to update our component’s state using the current state of the component. Directly accessing this.state to update our component is not a reliable way to update our component’s next state. From the React documentation: Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.
Discussions

reactjs - When to use an object in `setState` instead of using functional `setState`? - Stack Overflow
an object being passed as the argument for the setState method. However, a function may be used instead of an object for the purpose of formatting or for performing temporary calculations before updating the state attributes. Example use cases for function in place of an object: ... This is not correct, there is a huge difference between an object and a function. Yes any non primitive data type in javascript is originally an object, but that does it ... More on stackoverflow.com
🌐 stackoverflow.com
May 30, 2020
Understanding calling setState with a function instead of an object
I think you're overcomplicating it by thinking about it in terms of things "overriding" other things. Maybe a React team member can give a better technical explanation, but here's the basics from a layman's perspective: React will batch the calls to setState and update your component's state all at once, no matter whether you use the object or function syntax of setState. Every change you make in any setState call will be considered and recorded by React behind the scenes, they just don't update your actual component's this.state at that point. So in your example in point 3, all that matters is by the time you call this.setState({ counter: this.state.counter + 5 }); for the final time, this.state.counter will still be 0, so the result will be 0 + 5 = 5. What the function syntax does is gives you access to the internal state that React is keeping track of, which already contains the results of your previous setState calls. Again, this always happens anyway, you just don't normally have access to that incrementally updated state because React hasn't mutated your component's this.state yet. More on reddit.com
🌐 r/reactjs
9
9
August 26, 2019
Why does passing a function with your previous state as a parameter ensure that state is updated before the code is executed?
here is a more in-depth article https://www.freecodecamp.org/news/functional-setstate-is-the-future-of-react-374f30401b6b/ https://stackoverflow.com/questions/48209452/when-to-use-functional-setstate So, when React encounters “multiple functional setState() calls” , instead of merging objects together, (of course there are no objects to merge) React queues the functions “in the order they were called.”After that, React goes on updating the state by calling each functions in the “queue”, passing them the previous state — that is, the state as it was before the first functional setState() call (if it’s the first functional setState() currently executing) or the state with the latest update from the previous functional setState() call in the queue. The setState function can accept both an object and a function. And the code is actually checking what you pass in. A very over-simplification of the code would be: function setState(param) { if (typeof param === 'function') { //do this } else { //do this } } --- can somebody explain why calling another function updates the state? what you are doing is not calling a function. You are passing it a function definition (without calling it). You will often hear the word "callback" in javascript. This is a callback. If you aren't too familiar with it, it might help to try to understand it outside of React.setState first. a light illustration would be if I rewrote the code, and named the callback function instead of using an anonymous function. setCounter((prevState) => { return (prevState + 1) }) turned into function myCallbackFunction(arg) { return arg + 1 } setCounter(myCallbackFunction) //and then inside the setCounter itself function setCounter(cb) { this.state = { counter: 30 } if (typeof cb === 'function') { cb(this.state) } } As you can see... myCallbackFunction is passed to setCounter. Inside setCounter, it will call the callback function with the arg/param that setCounter itself has access to, which in this case is the state. Although, with setState, it's not just calling the callback function. It's calling it, getting the result of the function internally, and then doing something with it More on reddit.com
🌐 r/react
3
10
December 3, 2021
reactjs - Should a function always be used for a setState that gets passed an array or object? - Stack Overflow
Wanting to improve my understanding of React in functional components I've seen some that pass a seState with a function when spreading an array or object. When I reference the docs I see: Unlike ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
NGCC in Angular Ivy
iq.js.org › questions › react › why-we-need-to-pass-a-function-to-setstate
Why we need to pass a function to React setState() method?
April 22, 2026 - The reason behind for this is that setState() is an asynchronous operation. React batches state changes for performance reasons, so the state may not change immediately after setState() is called.
🌐
React
legacy.reactjs.org › docs › faq-state.html
Component State – React
Pass a function instead of an object to setState to ensure the call always uses the most updated version of state (see below).
🌐
Quora
quora.com › Why-is-it-a-good-idea-to-pass-a-function-to-setState-instead-of-an-object
Why is it a good idea to pass a function to setState instead of an object? - Quora
Quora is a place to gain and share knowledge. It's a platform to ask questions and connect with people who contribute unique insights and quality answers.
🌐
Reddit
reddit.com › r/reactjs › understanding calling setstate with a function instead of an object
r/reactjs on Reddit: Understanding calling setState with a function instead of an object
August 26, 2019 -

Hey,

I'm paraphrasing my understanding of calling setState with an object vs with a function. I've highlighted the bits on which I seek clarity.

The problem: setState calls are async for performance reasons. Which means that when you have a call like -

this.setState({ default: 'some default value' });
this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 2 });
this.setState({ counter: this.state.counter + 3 });

You might expect a total increment of 6, but only the last setState call with an increment of 3 will actually reflect (And not necessarily immediately; but when it happens, it'll be 3). It is worth noting that this is a problem only when our current sate depends on the previous state because we aren't sure if our current state is the latest one, there might be some async update yet to be performed.

This result of 3 is because React will group multiple calls and create one final updated state object to be set, so that there will be only one final render, instead of separately making each state update and a respective render each time. Similarly, if we had set default multiple times, the last one would have been the one reflected.

So the new state object created for each setState will first have set to { counter: this.state.counter + 1 }, and then counter will be overridden by { counter: this.state.counter + 2 } and finally overridden again by { counter: this.state.counter + 3 }.

To solve this, we pass setState a function rather than an object.

this.setState((prevState, currentProps) => ({ counter: prevState.counter + 1 }));
this.setState((prevState, currentProps) => ({ counter: prevState.counter + 2 }));
this.setState((prevState, currentProps) => ({ counter: prevState.counter + 3 }));

What I am confused about

  1. Assuming an initial counter value of 0, the function passed setState will resolve to { counter: 0 + 1 } on the first call, { counter: 1 + 2 } in the second and { counter: 3 + 3 } in the third. And then just like previously, the final state object, which will be a merge of all the setState calls' objects, the last set to update counter will override the previous ones - but having access to an updated previous state avoids any discrepancies. Correct?

  2. Does this make the bits that pass a function to setState synchronous? (Because otherwise prevState won't necessarily be updated for the subsequent `setState` calls that also pass a function and access prevState)

  3. As a corollary of 2, if there are calls to setState like this -

this.setState({ counter: this.state.counter + 1 });
this.setState({ counter: this.state.counter + 2 });
this.setState((prevState, currentProps) => ({ counter: prevState.counter + 3 }));
this.setState((prevState, currentProps) => ({ counter: prevState.counter + 4 }));
this.setState({ counter: this.state.counter + 5 });

Will call 1, 2 and 5 happen asynchronously in a batch with 5 overriding 1 and 2 while 3 and 4 will be sync calls giving the counter 5 a state of 7 in addition to the initial value of counter?

I'd be grateful if someone could please validate my understanding.

TIA

EDIT: grammar and formatting and added point 3.

Top answer
1 of 4
6
I think you're overcomplicating it by thinking about it in terms of things "overriding" other things. Maybe a React team member can give a better technical explanation, but here's the basics from a layman's perspective: React will batch the calls to setState and update your component's state all at once, no matter whether you use the object or function syntax of setState. Every change you make in any setState call will be considered and recorded by React behind the scenes, they just don't update your actual component's this.state at that point. So in your example in point 3, all that matters is by the time you call this.setState({ counter: this.state.counter + 5 }); for the final time, this.state.counter will still be 0, so the result will be 0 + 5 = 5. What the function syntax does is gives you access to the internal state that React is keeping track of, which already contains the results of your previous setState calls. Again, this always happens anyway, you just don't normally have access to that incrementally updated state because React hasn't mutated your component's this.state yet.
2 of 4
2
useState is secretly useReducer under the hood (there's a little bit of extra debugging info added, but it ultimately calls the same internal machinery). Here's what it's implemented as: function useState(initial) { const [state, dispatch] = useReducer((currentState, action) => { if (typeof action === "function") { return action(currentState); } else { return action; } }, initial); return [state, dispatch]; } When dispatch (and hence when setState) is called multiple times, the actions are put into a queue. When the next render happens (and a render will be scheduled "soon" as soon as the first item is added, but might take a while) the queue will be emptied and each action will be applied in-order. That means any functions passed to setState will transform the state in the order they're used. Applying this to your questions: Assuming an initial counter value of 0, the function passed setState will resolve to { counter: 0 + 1 } on the first call, { counter: 1 + 2 } in the second and { counter: 3 + 3 } in the third. And then just like previously, the final state object, which will be a merge of all the setState calls' objects, the last set to update counter will override the previous ones - but having access to an updated previous state avoids any discrepancies. Correct? There's no "merging" and no "overriding"; the functions are applied in sequence, each with the result of the previous. So it's really computing add3(add2(add1(previousState))) right when you render. Does this make the bits that pass a function to setState synchronous? (Because otherwise prevState won't necessarily be updated for the subsequent setState calls that also pass a function and access prevState) Reducer actions are placed into a queue. They don't run immediately. However, all of the items in the queue are run in-order, synchronously at the time of the next render. With forthcoming fibers/suspense, this means they might run multiple times, since React might start rendering a component and then abandon it before coming back again later (although I don't think the exact behavior has been specified yet, and doing what I just suggested would likely break existing brittle code). As a corollary of 2, if there are calls to setState like this - this.setState({ counter: this.state.counter + 1 }); this.setState({ counter: this.state.counter + 2 }); this.setState((prevState, currentProps) => ({ counter: prevState.counter + 3 })); this.setState((prevState, currentProps) => ({ counter: prevState.counter + 4 })); this.setState({ counter: this.state.counter + 5 }); As the queue gets emptied, the intermediate values (starting from c) would be c+1 (replaced by c+1), c+2 (replaced by c+2), c+5 (added +3), and c+7 (added +4), and finally returning c+5 (replaced by c+5).
🌐
Reddit
reddit.com › r/react › why does passing a function with your previous state as a parameter ensure that state is updated before the code is executed?
r/react on Reddit: Why does passing a function with your previous state as a parameter ensure that state is updated before the code is executed?
December 3, 2021 -

Currently doing Maximilian Schwarzmüller's Udemy React course, and there is a lesson that seems important but which I don't quite understand the logic behind.

He said that whenever you are updating state in a way that depends on the previous state (for example, updating a state object where you're only changing one value, or updating a counter with state) you should NOT simply call the previous state variable in your setState function, but instead you should call another function where you pass the previous state in as a parameter, and return your new value. He said that this will ensure that your previous state is up to date before running the code.

For example, this is incorrect, because the value of counter could be out of date in the clickHandler function:

const [counter, setCounter] = useState(0);

const clickHandler = () => {
    setCounter(counter + 1)
};

and instead, you should do this:

const [counter, setCounter] = useState(0);

const clickHandler = () => {
    setCounter((prevState) => {
        return (prevState + 1)
    })
}

I can certainly just memorize this principle, but I don't understand exactly why it works. Can somebody explain why calling another function updates the state? I guess I don't really understand the "prevState" variable or how it is being assigned the value of the most updated state.

Top answer
1 of 1
4
here is a more in-depth article https://www.freecodecamp.org/news/functional-setstate-is-the-future-of-react-374f30401b6b/ https://stackoverflow.com/questions/48209452/when-to-use-functional-setstate So, when React encounters “multiple functional setState() calls” , instead of merging objects together, (of course there are no objects to merge) React queues the functions “in the order they were called.”After that, React goes on updating the state by calling each functions in the “queue”, passing them the previous state — that is, the state as it was before the first functional setState() call (if it’s the first functional setState() currently executing) or the state with the latest update from the previous functional setState() call in the queue. The setState function can accept both an object and a function. And the code is actually checking what you pass in. A very over-simplification of the code would be: function setState(param) { if (typeof param === 'function') { //do this } else { //do this } } --- can somebody explain why calling another function updates the state? what you are doing is not calling a function. You are passing it a function definition (without calling it). You will often hear the word "callback" in javascript. This is a callback. If you aren't too familiar with it, it might help to try to understand it outside of React.setState first. a light illustration would be if I rewrote the code, and named the callback function instead of using an anonymous function. setCounter((prevState) => { return (prevState + 1) }) turned into function myCallbackFunction(arg) { return arg + 1 } setCounter(myCallbackFunction) //and then inside the setCounter itself function setCounter(cb) { this.state = { counter: 30 } if (typeof cb === 'function') { cb(this.state) } } As you can see... myCallbackFunction is passed to setCounter. Inside setCounter, it will call the callback function with the arg/param that setCounter itself has access to, which in this case is the state. Although, with setState, it's not just calling the callback function. It's calling it, getting the result of the function internally, and then doing something with it
Find elsewhere
🌐
React
react.dev › reference › react › useState
useState – React
Because you’re passing a function, React assumes that someFunction is an initializer function, and that someOtherFunction is an updater function, so it tries to call them and store the result. To actually store a function, you have to put () => before them in both cases.
🌐
Stack Overflow
stackoverflow.com › questions › 69944846 › should-a-function-always-be-used-for-a-setstate-that-gets-passed-an-array-or-obj
reactjs - Should a function always be used for a setState that gets passed an array or object? - Stack Overflow
Its probably best practice to pass a function to the useState dispatch to avoid renders getting out of sync, especially if you use asynchronous methods to update state, but also any time your new state is dependent on previous state (so like ...
🌐
React Bits
vasanthk.gitbooks.io › react-bits › content › patterns › 27.passing-function-to-setState.html
Passing Function To setState() · React Bits
Here’s the dirty secret about setState — it’s actually asynchronous. React batches state changes for performance reasons, so the state may not change immediately after setState is called. That means you should not rely on the current state when calling setState — since you can’t be ...
🌐
Reddit
reddit.com › r/reactjs › passing state: callback vs set function
r/reactjs on Reddit: Passing state: callback vs set function
February 24, 2023 -

I had a little discussion with my colleagues, who are frontend developers like me, about passing set functions from a parent component to its children. They think that when you share the state from useState hooks between components, passing callback is a good practice, but passing the set function is well too.

It is good, they say, to write code like this:

export const ModalController = () => {
  const [open, setOpen] = useState(false);
  return (
    {open && <Modal onClose={() => setOpen(false)}/>}
    <Button onClick={() => setOpen(true)}>OPEN MODAL</Button>
  );
};

But if you should change different fragments of the parent's state on various actions in a child component, passing the set function as is will be better. Like there:

interface StateType {
  name: string;
  description: string;
  birthDate: Date;
  phoneNumber: string;
}

export const ParentComponent = () => {
  const [complexState, setComplexState] = useState<StateType>();
  return <ComplexForm values={complexState} changeValues={setComplexState} />;
};

I don't like this approach because it breaks components' encapsulation. I think, to create a good component, you should keep in this component its state and actions which it is responsible for. Your component can provide some data and actions to its children, but the children shouldn't know anything about their parent's structure. When you pass the set function to the children, you give them direct control over the state of the parent. In my opinion, it leads to some problems:

  1. If you have several child components receiving the set function, you need to write something like onClick={setState(newValues)} or even onClick={(key, value) => setState((prev) => ({ ...prev, [key]: value }))} in each of them. If you have only one component, you should think about code flexibility and imagine that you could have more child components in the future.

  2. If you'll change the parent's state structure in the future (e.g. when you'll refactor your code), it will be necessary to change the parent's state structure in the components that receive the set function.

  3. You don't restrict the parent component's state changing in its children. I think, there can be a specific case when it can lead to some unexpected bugs (because other programmers or the future you change the parent component's state in a way it shouldn't be changed).

  4. If you use TS, you need to write a complex type such as React.Dispatch<React.SetStateAction<StateType>> in the props interface of every child component receiving the set function. It is not flexible and less readable than just () => void or (key: keyof StateType, value: SomeStateValue) => void.

  5. This approach is bad for your mindset after all. Maybe it is impossible to write the perfect code, but React developers in my opinion should design as flexible and independent components as possible when they have enough resources (e.g. time before the deadline) to do it.

And what about the case when the different fragments of the parent's state should be changed on various actions in a child component? You can handle it with the callback like this:

type CallbackInput = Partial<StateType>;

const callback = (input: CallbackInput) => {
  setState((prev) => Object.assign({ ...prev, ...input }));
};

So, I believe, it is always better to use a callback instead of a set function when you pass your state to children components. What do you think about it? Are my arguments valid for you or you can challenge them?

Top answer
1 of 3
5
I think the callback is not inherently mandatory, and the set can be passed down. Whether it's a callback or a setter shouldn't matter, since the child should not be aware of this. What I mean is, that from the point of view of the child, you should define the prop as though it's a callback on an action triggered by the child component (onSomething callback prop). However, if this signature matches the setter of your useState, I see no reason why the parent should have to wrap it in a callback function. If later, the state of the parent becomes more complex, you can still wrap it in a callback, and the modification will be limited to only the parent component. It's the responsibility of the parent to know whether a setter or a callback is required, since this is dependent on their internal workings, of which the child component should not be aware. For me, a callback function implementation should add something, and not just pass exactly it's parameters to another function, that only adds unnecessary overhead, without increasing readability. const [value, setValue] = useState() return looks to me perfectly fine. The most important part is to not "bleed" the parent logic into the child. If it is natural for the child to have the complex state, by all means, give it, but if it doesn't, make it so it doesn't have it, by only passing a fragment of the state and to use a proper callback function. Usually, a component that needs a fragment of a state (so more than a single field) makes me think of a code smell, where the state should not be contained in a single useState. The single state object was a pattern of the class component, but with functional components, it's usually better to have multiple smaller states.
2 of 3
1
Literally doesn’t matter. Worrying about this is probably over engineering
Top answer
1 of 3
2

In the first case when you add todos as a dependency to useCallback, the function will be recreated again each time you call it since it is setting todos state itself and hence will not be optimized for memoization

In the second case, you are using the callback version os state updater which essentially will provide you the previous state as an argument to callback and the function will be only created once.

This should be the preferred approach

To know more about the advantages of functional setState, please check the linked post:

2 of 3
2

1) why does it render components quicker?

  • the performance gain of second code is not come from functional setState()
  • you use useCallback() to memoize the function onRemove(), so it won't be created every time the component re-render.
  • you pass no dependencies, so the function onRemove() will be created only once - when the component mounts

2) What are the other advantages of using functional setState()?

functional setState() is used to escape closure

  • use static state
import React, { useState, useEffect } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);
  console.log('render');

  useEffect(() => {
    console.log('componentDidUpdate')

    const id = setInterval(() => {
      setCount(count)  // count is always 0 because the variable count is closured
    }, 1000);

    return () => {
      clearInterval(id);
      console.log('clean');
    }
  }, []); // run only once when the component mounts

  return (
    <h1>
      {count}
    </h1>
  )
}

export default Counter;
  • use functional setState() to read fresh state
import React, { useState, useEffect } from 'react';

const Counter = () => {
  const [count, setCount] = useState(0);
  console.log('render');

  useEffect(() => {
    console.log('componentDidUpdate')

    const id = setInterval(() => {
      setCount(count => count + 1); // read fresh value of count
    }, 1000);

    return () => {
      clearInterval(id);
      console.log('clean');
    }
  }, []); // run only once when the component mounts

  return (
    <h1>
      {count}
    </h1>
  )
}

export default Counter;

Reference

  • A Complete Guide to useEffect
🌐
CSS-Tricks
css-tricks.com › understanding-react-setstate
Understanding React `setState` | CSS-Tricks
February 8, 2019 - let count = 3 const object = Object.assign({}, {count: count + 1}, {count: count + 2}, {count: count + 3} ); console.log(object); // output: Object { count: 6 } So instead of the call happening three times, it happens just once. This can be fixed by passing a function to setState().
Top answer
1 of 3
59

First things first, in your case the two syntaxes are entirely different, what you might be looking for is the difference between

this.setState({pictures: this.state.picture.concat(pics)})

and

this.setState(prevState => ({
   pictures: prevState.pictures.concat(pics)
}))

To understand why the second method is a preferred one,you need to understand what React does with setState() internally.

React will first merge the object you passed to setState() into the current state. Then it will start that reconciliation thing. Because of the calling setState() might not immediately update your state.

React may batch multiple setState() calls into a single update for better performance.

Consider the simple case, to understand this, in your function you might call setState() more than once like:

myFunction = () => {

   ...
   this.setState({pictures: this.state.picture.concat(pics1)})
   this.setState({pictures: this.state.picture.concat(pics1)})
   this.setState({pictures: this.state.picture.concat(pics1)})

   ...
}

which isn't a valid use case in a simple app but as the app gets complex, multiple setState() calls may be happening from multiple places, doing the same thing.

So now to perform an efficient update, React does the batching thing by extracting all the objects passed to each setState() call, merges them together to form a single object, then uses that single object to do setState(). According to the setState() documentation:

This form of setState() is also asynchronous, and multiple calls during the same cycle may be batched together. For example, if you attempt to increment an item quantity more than once in the same cycle, that will result in the equivalent of:

Object.assign(
  previousState,
  {quantity: state.quantity + 1},
  {quantity: state.quantity + 1},
  ...
)

Subsequent calls will override values from previous calls in the same cycle, so the quantity will only be incremented once. If the next state depends on the current state, we recommend using the updater function form, instead:

this.setState((state) => {
  return {quantity: state.quantity + 1};
});

For more detail, see:

  • State and Lifecycle guide
  • In depth: When and why are setState() calls batched?
  • In depth: Why isn’t this.state updated immediately?

setState() - Other APIs - React.Component – React.

So if any of the objects contains the same key, the value of the key of the last object with same key is stored. And hence the update only happens once with the last value.

Demo Codesandbox

2 of 3
18

TL;DR: Functional setState is mainly helpful to expect correct state update when multiple setStates are triggered in a short interval of time where as conventional setState does reconciliation and could lead to unexpected state.

Please check this wonderful article on Functional setState to get a clear understanding

And here is the WORKING DEMO

Firstly, you are trying to do different things in each of your cases, you are assigning pics in one and concatenating pics in another.

Lets say this.state.pictures contain [1, 2, 3] and pics contain [4, 5, 6]

this.setState({pictures: pics})

In the above case this.state.pictures will contain the pics i.e this.state.pictures = [4, 5, 6]

this.setState(prevState => ({
   pictures: prevState.pictures.concat(pics)
}))

Whereas in the above snippet, this.state.pictures will contain the previous pictures + pics i.e this.state.pictures = [1, 2, 3, 4, 5, 6]

Either way you can tweak it to meet your API needs, if it's like a paginated response the you are better off concatenating the results on each request, else if you get the whole array each time just assign the whole array.

Conventional setState VS Functional setState

Now, your question mainly is probably whether to use setState with an object or with a function.

People use both of them for different reasons, now the functional setState is said to be safe because React does something called a reconciliation process where in it merges multiple objects inside setState when triggered frequently or concurrently and applies the changes in one shot, kind of like a batch process. This could potentially lead to some unexpected results in scenarios like below.

EXAMPLE:

increaseScoreBy3 () {
 this.setState({score : this.state.score + 1});
 this.setState({score : this.state.score + 1});
 this.setState({score : this.state.score + 1});
}

As you would expect the score to be incremented by 3 but what React does is merge all the objects and update the score only once i.e incrementing it by 1

This is one of the cases where functional callback shines because reconciliation does not happen on functions and executing the below code will do things as expected i.e update score by 3

increaseScoreBy3 () {
 this.setState(prevState => ({ score: prevState.score + 1 }));
 this.setState(prevState => ({ score: prevState.score + 1 }));
 this.setState(prevState => ({ score: prevState.score + 1 }));
}
🌐
freeCodeCamp
freecodecamp.org › news › functional-setstate-is-the-future-of-react-374f30401b6b
Functional setState is the future of React
March 3, 2017 - Updates will be queued and later executed in the order they were called. So, when React encounters “multiple functional setState() calls” , instead of merging objects together, (of course there are no objects to merge) React queues the functions “in the order they were called.” · After that, React goes on updating the state by calling each functions in the “queue”, passing them the previous state — that is, the state as it was before the first functional setState() call (if it’s the first functional setState() currently executing) or the state with the latest update from the previous functional setState() call in the queue.
🌐
Reddit
reddit.com › r/reactjs › why use functions when updating state variable in usestate()
r/reactjs on Reddit: Why use functions when updating state variable in useState()
February 21, 2022 -
const [state, updateState] = useState(0)

updateState(prevState => prevState+1) //Would output to 1

Why is this the recommended way to update states using useState?

updateState(prevState+1) //Would also output 1

Why not this?

I've tried searching for an explanation for this and this is the only one I got

const [state, updateState] = useState(0)

updateState(prevState+1) //Would also output 1
updateState(prevState+1) //Wouldn't output 2, still outputs 1

The explanation I got from this was that the second updateState still references for state with the value of 0

const [state, updateState] = useState(0)

updateState(prevState => prevState+1) //Would output to 1
updateState(prevState => prevState+1) //Would output to 2

But why does this work? What's the underlying mechanism difference between the two?

Thanks!

Top answer
1 of 8
17
state is a binding. It is bound to the “real” state value that React manages under the hood when the const [state, updateState] = useState(0) statement is executed. setState will update the “real” state value but it doesn't have access to the state binding. The binding only exists in your component. When you call setState(state + 1) when state is 0, React updates the “real” state value to 1, but state remains 0. So the next call will again update the value to 1, because 0 + 1 still equals 1. setStates also schedules a re-render, during rerender, your component (which is a JS function) is executed again. In the context of this particular execution state is now bound to the latest value. The functional setState call always passes the latest value to your updater function so the second update isn't lost.
2 of 8
7
Imagine it this way: const [state, updateState] = useState(0) // in this context: prevState = 0; it will not be updated during the function execution, since it is defined as const in upper scope // so both time prevState + 1 will equal 1 // therefore you are twice setting the state to be 1 and not incrementing it twice updateState(prevState+1) //Would also output 1 updateState(prevState+1) //Wouldn't output 2, still outputs 1 But if you call it with callback: //prevState will point to whatever value the state has, when the function was invoked //so you are calling it first time, prevState = 0 updateState(prevState => prevState+1) //Would output to 1 // then it updates internally and is now 1, so you call it second time and now it points // to the current value which is 1, therefore output is 2 updateState(prevState => prevState+1) //Would output to 2
🌐
Hands on React
handsonreact.com › state
State | Hands on React
So if the new state is computed using the previous state...pass a function to your updater function (setX function). The function will receive the previous value, and return an updated value. Here’s an example of a counter component that uses both forms of setState:
🌐
Reacttraining
reacttraining.com › blog › react-state-common-questions
2 of 3 React State: Common Questions?
May 24, 2021 - Then when we changed state with setState, we would provide an object and the API would "merge" its contents into the existing state for us. This doesn't happen with setting state in function components with useState. ... You'd end up destroying state you didn't mean to, like the error in this case because calling setState will <u>replace</u> all existing state that you're storing in that particular call to useState.