【问题标题】:ReactJS: Update nested state object properties without replacing whole object using setState()ReactJS:更新嵌套状态对象属性而不使用 setState() 替换整个对象
【发布时间】:2019-04-30 23:29:28
【问题描述】:

在我的组件状态中更改嵌套对象的多个属性值时,我正在尝试应用最佳实践。

我的组件代码目前如下所示:

class App extends Component {
  state = {
    object: {
      a: 10,
      b: 7,
      c: 12,
    }
  }
  render() {
    return (
      <div>
        <button onClick={this.setState({ object: { a: 5 }})}>change value a </button>
        <button onClick={this.setState({ object: { b: 2 }})}>change value b </button>
        <button onClick={this.setState({ object: { c: 3 }})}>change value c </button>
      </div>
      <p>{this.state.object.a}</p>
      <p>{this.state.object.b}</p>
      <p>{this.state.object.c}</p>
    );
  }
}

在单击任何按钮之前,您会在页面上看到三个按钮,后面是 10712 的段落。

一旦我单击第一个标记为“更改值 a”的按钮,值 bc 在我的组件状态对象中被破坏,这导致仅显示 5 的值。如果我点击第二个按钮,那么只有2 会显示并且支持ac 消失了。

我了解这种行为,但我想知道解决它的最佳方法。我想保留它,以便显示所有值,并能够在其他值保留时以任何顺序更新它们。

我也很确定我正在直接改变状态,我知道这是不好的做法。我只是不知道在这种情况下正确的做法。

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

首先解决您所说的问题,“我正在直接改变状态”

您没有直接改变状态,因为您正在调用this.setState()

由于您要更新object: {} 的特定部分,您可以使用扩展语法或Object.assign(),如下所示:

this.setState({ object: { ...this.state.object, a: 5 } })

this.setState({ object: Object.assign({}, this.state.object, { a: 5 }) })

因为您在render 中调用了this.setState(),所以您将得到Maximum call stack exceeded error

我能想到四种方法来解决这个问题,我将展示其中的两种。

  1. 将您的调用提取到类方法中,然后将引用传递给 点击事件处理程序。
  2. 将此onClick={this.setState({ object: { c: 3 }})} 更改为onClick={() => this.setState({ object: { c: 3 }})}

【讨论】:

  • 使用传播运算符工作!谢谢!我实际上不得不从渲染中完成功能;它给了我“超出最大更新深度”错误
【解决方案2】:

一种方法是在嵌套的object 上使用扩展... 运算符将{ a: 5 } 的更新与object 字段的先前状态合并:

// Create a new state object, with updated value of "5" for nested field "object.a"
{ object: { ...state.object, a: 5 }}

有几种方法可以将它与setState() 结合起来——一种简单的方法是通过传递给setState() 的回调:

this.setState(state => { object: { ...state.object, a: 5 }})

这允许您将嵌套的objects 先前状态与{ a : 5 } 上的object 等状态更改合并,而无需完全替换您状态中的所有嵌套object 值。

对于您的渲染函数,您可以像这样更新渲染结果:

 render() {
  return (
  <div>
    <button onClick={ () => this.setState(state => { object: { ...state.object, a: 5 }})}>change value a </button>
    <button onClick={ () => this.setState(state => { object: { ...state.object, b: 2 }})}>change value b </button>
    <button onClick={ () => this.setState(state => { object: { ...state.object, c: 5 }})}>change value c </button>
  </div>
  <p>{this.state.object.a}</p>
  <p>{this.state.object.b}</p>
  <p>{this.state.object.c}</p>
  );
  }

【讨论】:

  • 使用传播运算符工作!谢谢!我实际上不得不从渲染中完成功能;它给了我“超出最大更新深度”错误。
  • @EricChristensen 很高兴听到 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-31
  • 1970-01-01
  • 2019-12-15
  • 1970-01-01
  • 1970-01-01
  • 2019-11-20
  • 1970-01-01
相关资源
最近更新 更多