正确更新嵌套属性的状态

时间:2018-08-29 07:15:24

标签: reactjs

我在组件状态下具有以下数据结构。所有状态属性都是受控组件。

System.setProperty("file.encoding","UTF-8");
 System.setProperty("sun.jnu.encoding","UTF-8");

例如,将第一级属性“公司名称”定义为

new String(byteArray, "UTF-8")

和第二级属性“ firstName”定义为

  constructor(props) {
  super(props);
  this.state = {
        companyName: '',
        country: '',
        contact: {
            firstName: '',
            lastName: '',
            email: '',
            phone: ''
        }
  };
  this.handleChange = this.handleChange.bind(this);
  this.handleSubmit = this.handleSubmit.bind(this);
}

我当前的handleChange(e)方法会更新状态,但会向该状态添加2级属性。更新状态的正确方法是什么?

<Input label="Company Name" name="companyName" id="companyName" type="text" value={this.state.companyName} onChange={this.handleChange} required/>

4 个答案:

答案 0 :(得分:2)

constructor(props) {
      super(props);
      this.state = {
         companyName: '',
         country: '',
         contact: {
             firstName: '',
             lastName: '',
             email: '',
             phone: ''
         }
      };
      // this.handleChange = this.handleChange.bind(this); => remove this, you don't need this, bind your functions where you define them using `=>` like I did in the example below
}

对于您的输入字段

<Input label="Company Name" name="companyName" id="companyName" type="text" value={this.state.companyName} onChange={this.handleChange('rootLevel')} required />

第二层财产

<Input label="First Name" name="firstName" id="firstName" type="text" value={this.state.contact.firstName} onChange={this.handleChange('contact')} required/>

onChange方法应该像这样

handleChange = type => event => {
  if (type === "rootLevel") {
    this.setState({ [event.target.name]: event.target.value });
    return;
  }
  const { name, value } = event.target;
  this.setState({
    [type]: {
      ...this.state[type],
      [name]: value
    }
  });
};

作为参考,我已在Codesandbox中复制了此代码,您可以查看[here]

答案 1 :(得分:1)

此问题是由于您两次添加[name]: value而引起的。因此,如果更新第一级属性,则还添加第二级属性,反之亦然。

我建议您使状态完全平坦。这样,您可以继续使用相同的handleChange方法。

state = {
   companyName: '',
    country: '',
    firstName: '',
    lastName: '',
    email: '',
    phone: ''
};

否则,您必须在handleChange方法中告诉您要更新属性的级别。像这样:

handleChange(event, level) {
   if (level === 1) { // or whatever way you think is best to get the right level
       this.setState({
           ...this.state, [event.target.name]: event.target.value
       });
   } else {
       this.setState({
           ...this.state, 
           content: {
               ...this.state.contact,
               [event.target.name]: event.target.value
           }
       });
   }
}

您的输入应如下所示:

<Input label="First Name" name="firstName" id="firstName" type="text" value={this.state.contact.firstName} onChange={(e) => this.handleChange(e, 2)} required/>

答案 2 :(得分:0)

您将[name]用于第一级和第二级哈希。 因此,如果您编辑firstName,它也会将firstName添加到第一级。 试试这个。

handleChange(e) {
  const { name, value } = e.target;
  if(['companyName', 'country'].includes(name)){
    this.setState( prevState => {
      ...prevState,
      [name]: value
    });
  }else{
    this.setState( prevState => {
      ...prevState,
      contact: {
        ...prevState.contact,
        [name]: value,
      }
   });
  }
}

答案 3 :(得分:0)

由于有些人已经给出了一些解决方案。 让我们考虑一下可以使用几行代码的解决方案。

handleChange(e) {
let contact = this.state.contact;
    if (contact.hasOwnProperty(e.target.name)) {
        contact[e.target.name] = e.target.value;
    }
    this.setState({
        [e.target.name]: e.target.value
    }); 
}

此解决方案有效。我认为您不应该使这种事情变得过于复杂,而应该保持状态不变,并且在发送数据时应重新格式化。