在Reactjs中设置嵌套对象状态的正确方法是什么?

时间:2019-04-08 06:04:49

标签: javascript reactjs setstate

此代码段重复了我目前在这家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的性能是否不取决于Spread运算符(...)?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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