DEV Community

Brian Gaines
Brian Gaines

Posted on

When should we use the appropriate way to set state?

I'm still new with React and am trying to understand when we would use each of the, according to React team, correct ways of setting state. I've seen both methods used, but confused when one way would be used over the other.

Why wouldn't we always use Option 2 below?

Here is the link to the React Docs on this section

Do Not Modify State Directly (Option 1)

this.setState({comment: 'Hello'});
Enter fullscreen mode Exit fullscreen mode

State Updates May Be Asynchronous (Option 2)

this.setState((state, props) => ({
  counter: state.counter + props.increment
}));
Enter fullscreen mode Exit fullscreen mode

alt text

Top comments (3)

Collapse
 
dance2die profile image
Sung M. Kim • Edited

** update **
Woops, 😅 I didn't catch that #explainlikeim5 tag...


Hi Brian,

Those two examples are actually recommended ways.
From what I read from docs, following examples are the wrong ways.

Do Not Modify State Directly

// Wrong
this.state.comment = 'Hello';

👆 is wrong because (short answer is that) React would not know whether this.state.comment is updated without this.setState(...).

Longer answer is due to React tracks state changes (Reconciliation).

A state is an object, thus a reference type. Checking whether each state in each object for all components in React tree would be prohibitively slow. So when you are doing this.setState({comment: 'Hello'}), you are basically setting a new reference for this.state and alerting React to queue the changes for render later.

When you do this.state.comment = "Hello", you didn't change the reference of this.state but only the value pointed by the reference thus React would not know that the state has changed.

State Updates May Be Asynchronous

// Wrong
this.setState({
  counter: this.state.counter + this.props.increment,
});

For this case, while you are changing counter state within this.setState, either this.state.counter & this.props.increment could have a difference value from the time you tried to set the counter value.

Suppose that in your code

// at the time you are calling `this.setState`
// `this.state.counter` is 1
// and `this.props.increment` is 1
this.setState({
  counter: this.state.counter + this.props.increment,
});

As setState is asynchronous, when React is trying to apply the setState, values for this.state.counter or/and this.props.increment (such as 2, 3, etc) could have changed by external event/side effects (e.g. setInterval, mouse, keyboard events, etc).

When you use the "correct" callback version,

// Correct
this.setState((state, props) => ({
  counter: state.counter + props.increment
}));

React knows what the previous state & props were and gives you the snapshot of those values, thus no need to worry about it being changed elsewhere.

I could be missing something or wrong somewhere.

If so, would anyone kindly point out my mistakes? 🙂 Thanks.

Collapse
 
briang123 profile image
Brian Gaines

Hi Sung,

Thanks for your reply!

Perhaps my question wasn't clear enough, sorry for that. I posted the two options (from the React docs) knowing that those were the correct ways to implement state, BUT my question is when to use one over the other. Why are there two correct ways when Option 2, IMO, should always be used. Why have Option 1, when there's Option 2? Hope that clears it up.

Collapse
 
dance2die profile image
Sung M. Kim • Edited

Yikes.. I am sorry I misunderstood the question 😰

How I understood was that they are basically the same providing devs multiple ways to do the same thing depending on your need.

So if you don't need to use previous state or props, then go with option 1 else option 2.

Unrelated to the main question,
For memoization in React Hooks, they have two different ways to memoize (useCallback & useMemo, which do the same thing but useCallback is called like Option 1 of setState, while useMemo is called like Option 2 of setState).

Official doc shows that

useCallback(fn, inputs) is equivalent to useMemo(() => fn, inputs).

But I don't know enough history about React why there is only setState but two for memoization 😅