React js Change Field с указанием имени атрибута - PullRequest
0 голосов
/ 27 сентября 2019

У меня есть атрибуты в состоянии, я хотел бы убедиться, что, указав функцию, имя атрибута изменяет значение, содержащееся в состоянии.

Кажется, это работает, проблема в том, что если у меня есть объектэтого типа в состоянии:

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

Он не работает должным образом, так как код теперь устанавливается в состояние, в этом случае создается новый атрибут.

Так что я быхотел бы сделать что-то вроде этого:

handleChangeField("companyInfo.name")

Он изменяется на имя атрибута состояния объекта obj companyInfo, находящегося в штате.

Можете ли вы дать мне несколько советов?

Ссылка: коды и поле

Код:

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"));

1 Ответ

1 голос
/ 27 сентября 2019

Редактировать: я придумал гораздо лучший ответ, в котором мутировал конкретный ключ oldState, используя уменьшение.Меньше кода, гораздо более элегантно и должно работать на любой глубине объекта.

Рабочий пример здесь

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);
  };

Что происходит шаг за шагом в функции уменьшения, если вы выполните handleChangeField('company.name') с evt.target.value = "Big Corp":

1), вы получитемассив ['name','company']

2) вы входите в функцию уменьшения

  • при 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'}
...