【问题标题】:What is the correct way to set state of a nested objects in Reactjs?在 Reactjs 中设置嵌套对象状态的正确方法是什么?
【发布时间】:2019-04-08 06:04:48
【问题描述】:

这段代码 sn-p 从我目前在这家 X 公司工作的软件中复制了我的问题。

import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';

class App extends Component {
  constructor() {
    super();
    this.state = {
      name: 'React',
      some:{
        name:"axys",
        a:[1,2.23,46,612,5],
        z:{
          a:2,
          b:5,
          c:6,
        }
      }
    };
  }

handler = () =>{
  console.log(this.state);
  this.setState({
    some:{
      z:{
        a:1111
      }
    }
  },()=>{
    console.log(this.state);
  })
}

  render() {
    return (
      <div>
        <Hello name={this.state.name} />
        <button onClick = {this.handler}>
          Change State
        </button>
      </div>
    );
  }
}

render(<App />, document.getElementById('root'));

假设我想更改 this.state.some.z.a 的值,虽然我最初是

this.setState({
    some:{
      z:{
        a:1111
      }
    }
}

但事实证明返回给我的状态是

{
  "name": "React",
  "some": {
    "z": {
      "a": 1111
    }
  }
}

所以要获得我需要编写的预期输出

this.setState({
    some:{
      ...this.state.some,
      z:{
        ...this.state.some.z,
        a:1111
      }
    }
  }

所以我的问题是,这是正确/推荐的做事方式还是我错过了什么。

如果这是正确的方法,setState 的性能不会依赖于扩展运算符(...)吗?

【问题讨论】:

  • 这是正确/推荐的方式吗?我猜是的。
  • 这是一种正确的方法。您还可以使用深度克隆功能(例如从 lodash 或滚动您自己的功能)首先克隆它,更改单个道具然后将整个对象重新加载到状态。但基本上是的,你不能在不创建整个对象的新实例的情况下更改反应状态下的单个嵌套值。记住传播运算符不做深拷贝:bambielli.com/til/2017-01-29-spread-operator-deep-copy/#
  • 您的代码删除了除this.state.some.z.a 之外的所有其他代码。你想要它们还是你的代码输出适合你?

标签: javascript reactjs setstate


【解决方案1】:

正如其他人所提到的,有多种方法可以做您想做的事情。但是正确你提到的具体方法是使用prevState,因为this.state是不可靠的(因为它是异步的)。

这是一个工作示例:

this.setState((prevState, props) => ({
  some: {
    ...prevState.some,
    z: {
      ...prevState.some.z,
      a: 1111
    }
  }
}))

很好的解释:https://teamtreehouse.com/community/react-docs-now-recommends-using-function-with-prevstate-inside-of-setstate

【讨论】:

    【解决方案2】:
    there are two ways to do it 
    
    1. copy the object into some:
    
        handler = () => {
            let some = Object.assign({}, this.state.some);
            some.z.a = 1111;
            this.setState({ some }, () => {
              console.log(this.state);
            });
          };
    
    will give an output:
    
        {
        name: "React"
        some: Object
        name: "axys"
        a: Array[5]
        z: Object
        a: 1111
        b: 5
        c: 6}
    
    2. using the spead oprator
        handler = () => {
            let some = { ...this.state.some };
            console.log(some)
            this.setState(
              prevstate => ({
                some: {
                 z:{ ...prevstate.some.z,
                  a: 1111}
                }
              }),
              () => {
                console.log(this.state);
              }
            );
          };
    
    with solution:
    
        {name: "React"
        some: Object
        z: Object
        a: 1111
        b: 5
        c: 6}
    hope it will help
    

    【讨论】:

      猜你喜欢
      • 2020-08-26
      • 2018-01-24
      • 2022-07-07
      • 1970-01-01
      • 1970-01-01
      • 2015-07-21
      • 2020-11-02
      • 2021-10-09
      • 1970-01-01
      相关资源
      最近更新 更多