【问题标题】:React js Change Field specifying the attribute nameReact js更改字段指定属性名称
【发布时间】:2020-01-27 15:51:20
【问题描述】:

我在状态中有属性,我想通过指定函数来确保属性名称改变状态中包含的值。

似乎可以,问题是如果我在状态中有这种类型的对象:

companyInfo: {
  name: "",
  vatNumber: "",
  legalRepresentative: ""
}

它不能正常工作,因为代码现在设置在这种情况下的状态下,会创建一个新属性。

所以我想做这样的事情:

handleChangeField("companyInfo.name")

改为该状态的obj companyInfo的状态属性名。

你能给我一些建议吗?

链接:codesandbox

代码:

import ReactDOM from "react-dom";
import React, { Component } from "react";
import ReactJson from "react-json-view";

class Todo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      email: "email0",
      role: "role0",
      companyInfo: {
        name: "",
        vatNumber: "",
        legalRepresentative: ""
      }
    };
  }

  returnStateElement = (...elements) => {
    const copy = Object.assign({}, this.state);
    return elements.reduce((obj, key) => ({ ...obj, [key]: copy[key] }), {});
  };

  handleChangeField = field => evt => {
    let state = {};
    state[field] = evt.target.value;
    this.setState(state);
  };

  handleSubmit = () => {
    let el = this.returnStateElement(
      "name",
      "email",
      "vatNumber",
      "legalRepresentative",
      "role"
    );
    let { name, email, legalRepresentative, vatNumber, role } = el;
    let dataSender = {};

    dataSender.email = email;
    dataSender.role = role;
    dataSender.companyInfo = {};
    dataSender.companyInfo.name = name;
    dataSender.companyInfo.legalRepresentative = legalRepresentative;
    dataSender.companyInfo.vatNumber = vatNumber;
    console.log(this.state);
    //console.log(dataSender)
  };

  render() {
    return (
      <div>
        <input onChange={this.handleChangeField("email")} />
        <br />
        <br />
        <input onChange={this.handleChangeField("companyInfo.name")} />
        <br />
        <br />
        <button onClick={() => this.handleSubmit()}>send</button>
        <br />
        <br />
        <ReactJson src={this.state} theme="solarized" />
      </div>
    );
  }
}

ReactDOM.render(<Todo />, document.getElementById("root"));

【问题讨论】:

    标签: reactjs object input react-state


    【解决方案1】:

    编辑:我想出了一个更好的答案,即使用 reduce 改变 oldState 的特定键。更少的代码,更优雅,并且可以在任何对象深度下工作。

    工作示例here

    setNestedField(object, fields, newValue) {
       fields.reduce((acc, field, index) => {
         if (index === fields.length - 1) {
           acc[field] = newValue;
         }
         return acc[field];
       }, object);
    
       return object;
     }
     handleChangeField = field => evt => {
       const fields = field.split(".");
       let oldState = this.state;
    
       const newState = this.setNestedField(
         { ...oldState },
         fields,
         evt.target.value
       );
    
       this.setState(newState);
     };
    
    

    老答案

    handleChangeFields 看起来像这样:

    handleChangeField = field => evt => {
        //first you split by '.' to get all the keys
        const fields = field.split(".").reverse();
    
        // you'll need the previous state
        let oldState = this.state;
    
        let newState = fields.reduce((acc, value, index) => {
          if (index === 0) {
           // you add the event value to the first key
            acc[value] = evt.target.value;
            return acc;
          }
    
          //copy acc to use it later
          const tmp = { ...acc };
    
          //delete previous key added to acc 
          delete acc[fields[index - 1]];
    
          acc[value] = { ...oldState[value], ...tmp };
          return acc;
    
      }, {});
        this.setState(newState);
      };
    

    如果你用evt.target.value = "Big Corp"handleChangeField('company.name'),那么在reduce 函数中一步一步发生了什么:

    1) 你得到数组['name','company']

    2) 你进入reduce函数

    • index = 0, acc = {}, key='name' => {name: 'Big Corp'}
    • index=1,acc= {name: 'Big Corp'},key='company'=>acc = { company: {name: 'Big Corp'}, name: 'BigCorp}所以在返回之前我们删除之前的key(这里是名字)返回=>{ company: {name: 'Big Corp'}

    【讨论】:

    • 它似乎工作但看这里,如果我添加另一个层,最后一个输入字段,会发生奇怪的事情,该对象的吸引力被消除:codesandbox.io/s/react-example-uduod
    • 确实,我找到了更好的方法来实现这一点
    • 最后两件事,根据您的说法,有一种方法可以使其也适用于数组,例如(companyInfo.el.ol.ar [1]):codesandbox.io/s/react-example-kz0w3 正如您从代码我有一个名为returnStateElement的函数,它应该只返回我想要的状态的属性,我遇到了一些问题,你可以看看,知道我哪里做错了:codesandbox.io/s/react-example-ebldv
    • 它会走得很远:)。如果您使用如此复杂的对象,我建议同时使用 lodash.setlodash.get 包。它们会让您的生活更轻松。
    猜你喜欢
    • 2014-08-25
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 2023-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多