如何在React中更新嵌套状态属性

JavaScript

GilGilPro

2020-03-10

我试图通过使用这样的嵌套属性来组织我的状态:

this.state = {
   someProperty: {
      flag:true
   }
}

但是像这样更新状态

this.setState({ someProperty.flag: false });

不起作用。如何正确完成?

第402篇《如何在React中更新嵌套状态属性》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

9个回答
梅小卤蛋梅 2020.03.10

try this code:

this.setState({ someProperty: {flag: false} });
SamJim 2020.03.10

I know it is an old question but still wanted to share how i achieved this. Assuming state in constructor looks like this:

  constructor(props) {
    super(props);

    this.state = {
      loading: false,
      user: {
        email: ""
      },
      organization: {
        name: ""
      }
    };

    this.handleChange = this.handleChange.bind(this);
  }

My handleChange function is like this:

  handleChange(e) {
    const names = e.target.name.split(".");
    const value = e.target.type === "checkbox" ? e.target.checked : e.target.value;
    this.setState((state) => {
      state[names[0]][names[1]] = value;
      return {[names[0]]: state[names[0]]};
    });
  }

And make sure you name inputs accordingly:

<input
   type="text"
   name="user.email"
   onChange={this.handleChange}
   value={this.state.user.firstName}
   placeholder="Email Address"
/>

<input
   type="text"
   name="organization.name"
   onChange={this.handleChange}
   value={this.state.organization.name}
   placeholder="Organization Name"
/>
十三西门 2020.03.10
stateUpdate = () => {
    let obj = this.state;
    if(this.props.v12_data.values.email) {
      obj.obj_v12.Customer.EmailAddress = this.props.v12_data.values.email
    }
    this.setState(obj)
}
Tony村村 2020.03.10

Create a copy of the state:

let someProperty = JSON.parse(JSON.stringify(this.state.someProperty))

make changes in this object:

someProperty.flag = "false"

now update the state

this.setState({someProperty})
乐猪猪 2020.03.10

I used this solution.

If you have a nested state like this:

   this.state = {
          formInputs:{
            friendName:{
              value:'',
              isValid:false,
              errorMsg:''
            },
            friendEmail:{
              value:'',
              isValid:false,
              errorMsg:''
            }
}

you can declare the handleChange function that copy current status and re-assigns it with changed values

handleChange(el) {
    let inputName = el.target.name;
    let inputValue = el.target.value;

    let statusCopy = Object.assign({}, this.state);
    statusCopy.formInputs[inputName].value = inputValue;

    this.setState(statusCopy);
  }

here the html with the event listener

<input type="text" onChange={this.handleChange} " name="friendName" />
伽罗Pro卡卡西 2020.03.10
const newState = Object.assign({}, this.state);
newState.property.nestedProperty = "new value";
this.setState(newState);
凯斯丁达蒙 2020.03.10

如果您使用的是ES2015,则可以访问Object.assign。您可以如下使用它来更新嵌套对象。

this.setState({
  someProperty: Object.assign({}, this.state.someProperty, {flag: false})
});

您将更新后的属性与现有属性合并,并使用返回的对象来更新状态。

编辑:将一个空对象作为目标分配给assign函数,以确保状态不会像carkod所指出的那样直接突变。

Harry逆天 2020.03.10

一行编写

this.setState({ someProperty: { ...this.state.someProperty, flag: false} });
LEYStafan 2020.03.10

为了setState创建嵌套对象,您可以按照以下方法进行操作,因为我认为setState无法处理嵌套更新。

var someProperty = {...this.state.someProperty}
someProperty.flag = true;
this.setState({someProperty})

这个想法是创建一个虚拟对象,对其执行操作,然后用更新的对象替换组件的状态

现在,散布运算符仅创建对象的一级嵌套副本。如果您的状态是高度嵌套的,例如:

this.state = {
   someProperty: {
      someOtherProperty: {
          anotherProperty: {
             flag: true
          }
          ..
      }
      ...
   }
   ...
}

您可以在每个级别使用传播运算符来设置状态,例如

this.setState(prevState => ({
    ...prevState,
    someProperty: {
        ...prevState.someProperty,
        someOtherProperty: {
            ...prevState.someProperty.someOtherProperty, 
            anotherProperty: {
               ...prevState.someProperty.someOtherProperty.anotherProperty,
               flag: false
            }
        }
    }
}))

但是,随着状态变得越来越嵌套,上述语法变得非常丑陋,因此,我建议您使用immutability-helperpackage更新状态。

有关如何使用更新状态的信息,请参见此答案immutability helper

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android