React:如何更新具有可变值和不可变值的状态

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

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

如果状态有两种类型的值,我们应该如何在 React 中更新状态?

例如

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

假设您需要一次更新所有属性(successerrorerrorMessages),实现它的最佳方法是什么?

至少我确定 errorMessages 不应该直接更新,因为它本质上是可变的,但是其余的呢?

我尝试了类似下面的操作,但结果是错误的。

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

只要您为 errorMessages 提供新值,React 就会正确更新状态。你不是在这里直接改变状态,你只是为字段提供一个新值,React 会做必要的改变:

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

所以假设你的状态原来是这样的

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

然后像这样

errorMessages创建一个新对象
const errorMessages = {
    ...this.state,
    "errorMessages": error.response.data,
};

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

那么,你的下一个状态大概是这样的,不知道是不是你想要的

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

您可能想直接分配新状态,这实际上是您创建的 errorMessages const,您刚刚完成它;)

之所以会这样,是因为当给一个没有值的对象添加变量时,只是按名称,javascript会自动将标签命名为与变量相同的名称,例如:

const a = 10;
const b = {
  a
};

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

有3种更新状态的方法:

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 })