40

I think it might be silly question to ask but trust me I am beginner to reactJS . Could someone please explain me why we use prevState in ReactjS . I tried hard to understand but failed .

Here is my code. Please Help me to understand

 state = {
    placeName : '',
    places : []
}



placeSubmitHanlder = () => {
    if(this.state.placeName.trim()===''){
      return;
    }
    this.setState(prevState => {
      return {
        places : prevState.places.concat(prevState.placeName)
      };
    });
  };
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
  • 6
    I don't think that this post is a 1:1 duplicate to of the linked post that its claimed to be a duplicate of. For one, the linked post asks *three* questions all at once, when you're supposed to ask 1 question per post on SO. This post is focused on one issue that newbies like me are asking as we learn. The richest part of all of this is that `prevState` isn't explicitly discussed in the react docs. The current top answer to this post elaborates on the what prevState is further than either the linked post this post is a supposed duplicate of or the react docs. – DeltaFlyer Apr 28 '19 at 22:05

3 Answers3

108

prevState is a name that you have given to the argument passed to setState callback function. What it holds is the value of state before the setState was triggered by React; Since setState does batching, its sometimes important to know what the previous state was when you want to update the new state based on the previous state value.

So if multiple setState calls are updating the same state, batching setState calls may lead to incorrect state being set. Consider an example:

state = {
   count: 0
}
updateCount = () => {
    this.setState({ count: this.state.count + 1});
    this.setState({ count: this.state.count + 1});
    this.setState({ count: this.state.count + 1});
    this.setState({ count: this.state.count + 1});
}

In the above code you might expect the value of count to be 4 but it would actually be 1 since the last call to setState will override any previous value during batching. A way to solve this to use functional setState:

updateCount = () => {
    this.setState(prevstate => ({ count: prevstate.count + 1}));
    this.setState(prevstate => ({ count: prevstate.count + 1}));
    this.setState(prevstate => ({ count: prevstate.count + 1}));
    this.setState(prevstate => ({ count: prevstate.count + 1}));
}
Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • 1
    Got it , Thanks . One Last question . Can you please explain this piece of code . `this.setState(prevState => { return { places : prevState.places.concat(prevState.placeName) }; });` –  Feb 21 '19 at 13:14
  • 1
    You can check [this](https://stackoverflow.com/questions/49425755/arrow-functions-and-the-use-of-parentheses-or-or/49425823#49425823) question for more details on that – Shubham Khatri Feb 21 '19 at 13:21
  • 1
    Actually I understood all behind the scene but confuse on this line `prevState.places.concat` What this means . Thanks –  Feb 21 '19 at 13:27
  • 2
    `prevState.places.concat(prevState.placeName)` will push previous placeName value in state to places state array and return a new array which we use to set places state – Shubham Khatri Feb 21 '19 at 13:31
  • sorry not understand .. –  Feb 21 '19 at 14:29
  • Let me explain . We have `prevState` function name and with this function we will access the value of places object after that we will concat .... ( Prevstate.placename ) is not clear to me ? –  Feb 21 '19 at 14:30
  • prevState is not a function name but an argument that is passed to callback to setState function and is just an object referring to previous value of state obj – Shubham Khatri Feb 21 '19 at 16:10
  • Can we use prev instead of prevState?? Seems to be working on mine. – Reactoo Jun 12 '21 at 10:05
12

You use it when you want to override the current state with the last state's parameters.

From React docs :

According to the React docs "React may batch multiple setState() calls into a single update for performance. Because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state."

"To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument"

Link

Community
  • 1
  • 1
S.Haviv
  • 311
  • 2
  • 14
  • 1
    @S.Haaviv Thank you for your comment . Could you please explain " Previous state value " as you mentioned in answer . Where Previous state is coming in my code. –  Feb 21 '19 at 12:55
  • 1
    When you use setState to set to a new state, prevState is the current state (inside the function of setState) . Because react can do some batching and it's async, the state may change over time so you can't rely on this. – S.Haviv Feb 21 '19 at 12:57
2

Here is a demo with a commented-out code to give you more information: http://codepen.io/PiotrBerebecki/pen/rrGWjm

constructor() {
  super();
  this.state = {
    value: 0
  }
}

React docs: https://facebook.github.io/react/docs/reusable-components.html#es6-classes

The [React ES6 class] API is similar to React.createClass with the exception of getInitialState. Instead of providing a separate getInitialState method, you set up your own state property in the constructor.

Where does prevState come from?

The prevState comes from the setState api: https://facebook.github.io/react/docs/component-api.html#setstate

It's also possible to pass a function with the signature function(state, props). This can be useful in some cases when you want to enqueue an atomic update that consults the previous value of state+props before setting any values. For instance, suppose we wanted to increment a value in state:

this.setState(function(previousState, currentProps) {
  return {
     value: previousState.value + 1
  };
});
Hardik Virani
  • 1,687
  • 7
  • 23
  • 36
  • Could you please explain what mean by Previous Value and where this value is coming from ? . –  Feb 21 '19 at 12:58
  • @user11037643 react is internally getting 'this.state' as 'previousState'. Btw, as S.Haviv and Shubham Khatri explained, in order to override batching, you have to pass a function rather than an obj. – hyukkyulee Aug 27 '21 at 16:38
  • @user11037643 here is what 'setState' actually does under the hood ``` setState( state: ((prevState: Readonly, props: Readonly

    ) => (Pick | S | null)) | (Pick | S | null), callback?: () => void ): void;``` so your ``` state = { placeName : '', places : [] }``` will be your 'previousState' or whatever variable name you put in for first paramater for the callback function(```function(previousState, currentProps) { return { value: previousState.value + 1 }; }```)

    – hyukkyulee Aug 28 '21 at 02:53