Как мне назвать мой реагирующий компонент для размещения элемента в моем вложенном JSON? - PullRequest
1 голос
/ 27 февраля 2020

Я использую React 16.13.0. У меня есть следующий компонент (src / container / FormContainer.jsx) ...

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

    this.state = {
      defaultCountry: 484,
      countries: [],
      provinces: [],
      newCoop: {
        name: '',
        type: '',
        ...
      },


    ...
  render() {
    return (
        <form className="container-fluid" onSubmit={this.handleFormSubmit}>

            <Input inputType={'text'}
                   title= {'Name'}
                   name= {'name'}
                   value={this.state.newCoop.name}
                   placeholder = {'Enter cooperative name'}
                   handleChange = {this.handleInput}

                   /> {/* Name of the cooperative */}

            <Input inputType={'text'}
                   title= {'Type'}
                   name= {'type'}
                   value={this.state.newCoop.type}
                   placeholder = {'Enter cooperative type'}
                   handleChange = {this.handleInput}

                   /> {/* Type of the cooperative */}

Мой входной компонент, src / components / Input.jsx, выглядит вот так ...

import React from 'react';

const Input = (props) => {
    return (
  <div className="form-group">
    <label htmlFor={props.name} className="form-label">{props.title}</label>
    <input
      className="form-input"
      id={props.name}
      name={props.name}
      type={props.type}
      value={props.value}
      onChange={props.handleChange}
      placeholder={props.placeholder}
    />
  </div>
)
}

export default Input;

Проблема в том, что мне нужно отправить запрос POST, где параметр "type" представлен следующим образом: JSON ...

{
    "name": "1872",
    "type": {
        "name": "Coworking Space"
    },
    ...
}

Как мне назвать второе поле ввода (поле типа) так, чтобы я мог отправить свой JSON с правильной структурой?

Редактировать: Дескриптор ввода и отправки функций. ..

  handleFormSubmit(e) {
    e.preventDefault();
    let coopData = this.state.newCoop;

    fetch('/coops/',{
        method: "POST",
        body: JSON.stringify(coopData),
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
      }).then(response => {
        response.json().then(data =>{
          console.log("Successful" + data);
        })
    })
  }
  handleClearForm() {
    // Logic for resetting the form
  }
  handleInput(e) {
       let value = e.target.value;
       let name = e.target.name;
   this.setState( prevState => ({ newCoop :
        {...prevState.newCoop, [name]: value
        }
      }), () => console.log(this.state.newCoop))
  }

Ответы [ 2 ]

1 голос
/ 29 февраля 2020

Есть и другие способы достичь этого, но я вижу, что 2 в пределах досягаемости

1. Сохраните newCoop в структуре, необходимой для вызова POST

this.state = {
  newCoop: {
    name: '',
    type: {
      name: ''
    }
  }
}

Измените значение, которое вы даете типу ввода

<Input inputType={'text'}
  title= {'Type'}
  name= {'type'}
  value={this.state.newCoop.type.name}
  placeholder = {'Enter cooperative type'}
  handleChange = {this.handleInput}
/>

, и настройте this.handleInput для обработки этого случая:

  • вам может потребоваться написать специальную handleTypeNameChange функцию
  • изменить this.handleInput так, чтобы она могла справиться с этим случаем

Это зависит в вашей функции this.handleInput - можете ли вы поделиться ею?

name, который вы вводите для ввода, является атрибутом html name. Не уверен, что вы используете его в handleInput.

2. Оставьте форму как ручку изменения формы данных в this.handleFormSubmit

this.handleFormSubmit = () => {
  const postData = { 
    name: this.state.newCoop.name, 
    type: {
      name: this.state.newCoop.type
    }
  }
  // POST postData
}

Опять же, это зависит от вашего handleFormSubmit кода.

Надеюсь, это поможет!


Подробнее о варианте 1:

Мне нравится этот подход. @heisenberg предложил решение для этого, но оно не очень хорошо масштабируется - оно работает, но добавление еще нескольких полей превратит этот код в нечто сложное для чтения и обслуживания.

Вы можете: * использовать путь к значению состояния, которое вы хотите обновить, для имени входа * в handleInput вы обновите значение состояния, расположенное по пути, указанному name

Вы можете написать handleInput следующим образом:

import { set } from "lodash";
[...]
  handleInput = e => {
    let value = e.target.value;
    let name = e.target.name;
    const newCoop = set(this.state.newCoop, name, value);
    this.setState({ newCoop });
  };

Я использовал для этого loda sh s set . Есть и другие способы сделать это - вы даже можете написать это сами, если вам действительно не нужны дополнительные зависимости.

Для того, чтобы это работало для newCoop.type.name, вам необходимо настроить имя входа

<input
  ...
  name={"type.name"} // <- use the path to the value you want to change
  value={this.state.newCoop.type.name}
  ...
/>

Здесь - это Codesandbox с рабочим примером. Для простоты я использовал обычный input, а не компонент.

0 голосов
/ 29 февраля 2020
  • Вы должны сформировать объект в методе this.handleFormSubmit, это будет легко, вам нужно просто сформировать объект в соответствии с вашими требованиями.

    handleFormSubmit = () => {
      //form json object as per required structure
      const formData= { 
        name: this.state.newCoop.name, 
        type: {
          name: this.state.newCoop.type
        }
      }
    
     // then send formData in axios or fetch ajax method.
    }
    

ОБНОВЛЕНИЕ

  • Я согласен с @bamse по поводу масштабируемости, теперь я изменил решение для лучшего масштабирования.

  • В этом решении нет необходимости устанавливать любой другой пакет.

  • Вам просто нужно добавить еще одну функцию для чтения name из компонента ввода, где вы можете присвойте {name:"type.name"} в точечном формате.


    handleInput = (e) =>{
      let self=this
      let value = e.target.value;
      let name = e.target.name;
      //update State
      this.setValue(self.state.newCoop,name,value) 
    }

     setValue = (obj,is, value) => {
       if (typeof is == 'string')
         return this.setValue(obj,is.split('.'), value);
       else if (is.length==1 && value!==undefined)
         return this.setState({obj: obj[is[0]] = value});
       else if (is.length==0)
         return obj;
       else
         return this.setValue(obj[is[0]],is.slice(1), value);
      }
  • ВХОД КОМПОНЕНТА изменяется: name= {'type.name'}

--------- ------------------------------------КОНЕЦ--- --------------------------------------

  • Причина, по которой вы не получаете Object в своей структуре, заключается в том, что вы дали name= {'type'} в компоненте INPUT.

    • Поэтому, когда вы обрабатываете поле ввода типа в методе handleInput, let name = e.target.name; - это "type".

    • Когда вы установитеState в {...prevState.newCoop, [name]: value }. Здесь [name] равно "type", что является ключом newCoop. ТАК это будет обновлять ключ type напрямую. Потому что ваше прохождение name= {'type'} в компоненте INPUT

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...