【问题标题】:how to update the following state, with a generic handleChange that works in the following scenario:如何使用适用于以下场景的通用 handleChange 更新以下状态:
【发布时间】:2019-01-06 08:57:51
【问题描述】:

我有一个组件和以下状态:

this.state = {
    form : {
        name : '',
        username: '',
        email: '',
        phone: '',
        address: {
            street: '',
            suite: '',
            city: '',
            zipcode: ''
        }
    }
}

在表单域中,我在onChange中使用如下方法:

handleChange(e) {
    const {name, value} = e.target;
    let copyState = Object.assign({}, this.state);
    copyState.form[name] = value;
    this.setState(copyState);
}

这里是一个函数式表单域的例子:

<input value={this.state.form.username} 
    onChange={this.handleChange} 
    name="username"
    type="text" 
    className="form-control" 
/>

这不起作用:

<input value={this.state.form.address.street} 
   onChange={this.handleChange} 
   name="address.street"
   type="text"
   className="form-control" 
/>

handleChange 方法在以下项目上完美运行:姓名、用户名、电子邮件和电话,但在属于地址的属性中却不行。

如何解决?

非常感谢。 :)

【问题讨论】:

    标签: javascript reactjs state


    【解决方案1】:

    因为addressform 状态内的嵌套对象。我们可以这样做: 您可以像这样更改 handleChange 函数:

    handleChange = (name, value, isAddress) => {
      let { form } = this.state;
      let {address}=form
      if(isAddress){
        address[name]=value
      }else{
      form[name] = value;      
      }    
      this.setState({ form: {...form, address} });
    }

    您的组件代码将如下所示:

    class Forms extends React.Component {
      constructor() {
        super();
        this.state = {
          form: {
            name: "",
            username: "",
            email: "",
            phone: "",
            address: {
              street: "",
              suite: "",
              city: "",
              zipcode: ""
            }
          }
        };
        this.handleChange = this.handleChange.bind(this);
      }
    
      handleChange = (name, value, isAddress) => {
        let { form } = this.state;
        let {address}=form
        if(isAddress){
          address[name]=value
        }else{
        form[name] = value;      
        }    
        this.setState({ form: {...form, address} });
      }
    
      render() {
        let { form } = this.state;
    
        return (
          <div>
            Name: {form.name}
            <br />
            Username: {form.username}
            <br />
            email: {form.email}
            <br />
            phone: {form.phone}
            <br /> Street: {form.address.street}
            <br /> Suite: {form.address.suite}
            <br /> City: {form.address.city}
            <br /> Zipcode: {form.address.zipcode}
            <br />
            <input
              value={this.state.form.name}
              onChange={(e) => this.handleChange('name', e.target.value)}
              name="name"
              type="text"
              className="form-control"
            />
            <br />
            <input
              value={this.state.form.username}
              onChange={(e) => this.handleChange('username', e.target.value)}
              name="username"
              type="text"
              className="form-control"
            />
            <br />
            <input
              value={this.state.form.email}
              onChange={(e) => this.handleChange('email', e.target.value)}
              name="email"
              type="text"
              className="form-control"
            />
            <br />
            <input
              value={this.state.form.phone}
              onChange={(e) => this.handleChange('phone', e.target.value)}
              name="phone"
              type="text"
              className="form-control"
            />
            <br />
            <input
              value={this.state.form.address.street}
              onChange={(e) => this.handleChange('street', e.target.value, true)}
              name="street"
              type="text"
              className="form-control"
            />
            <br />
            <input
              value={this.state.form.address.suite}
              onChange={(e) => this.handleChange('suite', e.target.value, true)}
              name="suite"
              type="text"
              className="form-control"
            />
            <br />
            <input
              value={this.state.form.address.city}
              onChange={(e) => this.handleChange('city', e.target.value, true)}
              name="city"
              type="text"
              className="form-control"
            />
            <br />
            <input
              value={this.state.form.address.zipcode}
              onChange={(e) => this.handleChange('zipcode', e.target.value, true)}
              name="zipcode"
              type="text"
              className="form-control"
            />
            <br />
          </div>
        );
      }
    }

    这里是直播demo

    希望对你有帮助:)

    【讨论】:

    • 他要求一个通用的 handleChange 方法。
    • @joelgullander 对此感到抱歉。我已经更新了答案:)
    【解决方案2】:

    如果你想使用嵌套命名空间,你必须用点来分割,因为你不能这样做obj["foo.bar"]

    handleChange(event) {
      const path = event.target.name.split('.');
      const depth = path.length;
      const state = { ...this.state };
      let stateRef = state;
      for (let i = 0; i < depth; i += 1) {
        if (i === depth - 1) {
          stateRef[path[i]] = event.target.value;
        } else {
          ref = stateRef[path[i]];
        }
      }
      this.setState(state);
    }
    

    【讨论】:

    • 感谢您完成了 90% 的工作! else 中的 ref 应该是 stateRef。此外,对 JS n00bs 的工作原理的解释也会有所帮助。
    猜你喜欢
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 2021-11-15
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多