【问题标题】:React update state with nested object用嵌套对象反应更新状态
【发布时间】:2019-06-13 17:10:40
【问题描述】:

我有一个表单,当我提交它时,我想更新状态。现在只有名字和姓氏有效。我如何使用函数 handleChange 来更新嵌套对象的地址?还是我需要为此编写另一个函数? 感谢您的帮助

class Form extends Component {
  constructor(props){
    super(props);

    this.state = {
        name: '',
        surname: '',
        address: {
            street: '',
            city: '',
        },
    }
  }

  handleChange = e => {
    this.setState({ 
      [e.target.name]: e.target.value,   
    })
  }

  handleSubmit = e => {
    e.preventDefault();
  }

  render() {
    const {name, surname} = this.state;
    const { street, city} = this.state.address;

    return (
      <form onSubmit={this.handleSubmit}>
        <input type='text'
          value={name} 
          name='name'
          onChange={this.handleChange} />
        <input type='text'
          value={surname} 
          name='surname'
          onChange={this.handleChange} />
        <input type='text'
          value={street}
          name='street' 
          onChange={this.handleChange} />
        <input type='text'
          value={city} 
          name='city'
          onChange={this.handleChange} />
        <input type='submit' value='Submit' />
      </form>
    );
  }
}

【问题讨论】:

  • 您的代码无法更新name 和surname,因为没有提供name 属性(但您希望这是e.target.name)。你能实现代码sn-p吗?你认为name 字段address-&gt;city 是什么?
  • 为每个输入添加一个名称,然后在handleChange 中检查该名称,以将街道和城市与其他输入区分开来。

标签: javascript reactjs forms state


【解决方案1】:

我建议您为address 编写单独的更改处理程序。它将使您的代码简单易懂,而不是为这个简单的方法增加不必要的复杂性。

function handleAddressChange = e => {
    const {name, value} = event.target
    this.setState(({ address }) => {
        address: {
            ...address,
            [name]: value
        }
    })
}

【讨论】:

    【解决方案2】:

    您的表单元素中必须有name 属性,然后检查该名称值是否为setState。所以render() 方法看起来像这样

    render() {
      const {name, surname} = this.state;
      const { street, city} = this.state.address;
    
      return (
        <form onSubmit={this.handleSubmit}>
          <input type='text'
            name={name}
            value={name}
            onChange={this.handleChange} />
          <input type='text'
            name={surname}
            value={surname}
            onChange={this.handleChange} />
          <input type='text'
            name={street}
            value={street}
            onChange={this.handleChange} />
          <input type='text'
            name={city}
            value={city}
            onChange={this.handleChange} />
          <input type='submit' value='Submit' />
        </form>
      );
    }
    

    和handleChange()

    handleChange = e => {
      const name = e.target.name;
      if (name === 'city' || name === 'street') {
        this.setState({
          address: {
            ...state.address,
            [name]: e.target.value
          }
        });
      } else {
        this.setState({
          [name]: e.target.value
        });
      }
    };
    

    ... 是 ES6 Spread Operator,这是在 React 中更新嵌套状态的最简洁的方式。

    【讨论】:

    • 如果您在address 中添加新属性,例如zipCode / state,明天会发生什么,这是非常糟糕的主意。如果您重命名任何属性,那么您需要了解您正在以某种更容易出错的方法检查属性名称。
    • 我觉得没问题,你只需要在if (name === 'city' || name === 'street') 中添加一个检查,并在name 中添加一个input。但最终,这只是他问题的解决方案,仅此而已:)
    • 不,现在你可能认为这没关系,但相信硬编码属性名称是个坏主意。
    【解决方案3】:

    您只需要访问街道和城市?只需像这样首先解构地址。

    改变

    const {name, surname} = this.state;
    const { street, city} = this.state.address;
    

    到

    const {name, surname, address } = this.state;
    const { street, city} = address;
    

    【讨论】:

      【解决方案4】:

      我知道你们都面临过类似的任务,但重点是重新制作原始状态。 React 并不专注于处理嵌套状态。

      this.state = {
          name: '',
          surname: '',
          street: '',
          city: ''
      }
      

      【讨论】:

      • 嗯,这不是原始状态,重新创建它不是重点。我们怎么能假设没有充分的理由在状态中有一个不同的地址对象呢?假设她/他想将地址传递给另一个组件?使用扁平状态对象,他/她要么必须显式传递street 和city,要么传递整个状态。 OP 使用解构是正确的。它是 React 中的教科书用例。
      猜你喜欢
      • 1970-01-01
      • 2021-12-23
      • 2018-09-29
      • 2022-06-13
      • 2020-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多