简体   繁体   中英

React : how to update states which have both mutable and immutable values

In Javascript, string, integer and boolean values are immutable, but objects and arrays are mutable.

How should we update states in React, if states have both types of values?

eg

constructor(props) {
    super(props);
    this.state = {
        success: false,
        error: false,
        errorMessages: {}
    };
}

Assuming that you need to upgdate all of the properties ( success , error , errorMessages ) at once, what would be best way to achieve it?

At least I'm sure that errorMessages shouldn't be updated directly, because it's mutable by nature, but what about the rest of them?

I tried something like the following, but this ends up in a wrong result.

const errorMessages = {
    ...this.state,
    "errorMessages": error.response.data,
};

this.setState({
    errorMessages,
    success: false,
    error: true,
});

//The errorMessages property will have "success" and "error" property in it

As long as you supply a new value for errorMessages , React will update the state correctly. You're not mutating state directly here, you're just providing a new value for the field, and React will do the necessary mutation:

this.setState({
   errorMessages: error.response.data
   success: false,
   error: true,
});

So assuming your state is originally this

this.state = {
    success: false,
    error: false,
    errorMessages: {}
};

And then you create a new object for your errorMessages like this

const errorMessages = {
    ...this.state,
    "errorMessages": error.response.data,
};

this.setState({
    errorMessages,
    success: false,
    error: true,
});

Then, your next state will kinda look like this, and I am unsure if this is what you want

{
   errorMesages: {
     success: false,
     error: true,
     errorMessages: {
       // content of the error.response.data
     }
   },
   success: false,
   error: true
}

You probably wanted to assign the new state directly, which is in fact the errorMessages const you created, you are just over doing it ;)

The reason why this is so, is because when adding a variable to an object without a value, but just by name, javascript will automatically name the label the same as the variable, eg:

 const a = 10; const b = { a }; // result in: { a: 10 }; console.log(b); 

There are 3 ways to update state:

this.setState({
    success: !this.state.success,
    error: !this.state.error,
    errorMessages: delete this.state.id // if id were a prop in errorMessages
})

this.setState((prevState) => {
  return {
    success: !prevState.success,
    error: !prevState.error,
    errorMessages
  }
});

this.setState((prevState) => {
  return {
    success: !prevState.success,
    error: !prevState.error,
    errorMessages
  }
}, () => { // some callback function to execute after setState completes })

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM