Передача событий onChange через штат - PullRequest
1 голос
/ 18 апреля 2019

Я создаю компонент формы и хочу иметь возможность передавать элементы изменения для каждого элемента формы, и я не могу заставить его работать должным образом.

У меня есть LoginComponent

import React from "react";
import './LoginComponent.css';

import FormComponent from '../FormComponent/FormComponent';

class LoginComponent extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      header: "Login",
      id: "login-form",
      name: "login-form",
      items: [
        {
          element: "input",
          type: "email",
          id: "lf-email",
          name: "lf-email",
          value: "",
          onChange: this.handleOnChangeEmail.bind(this),
          placeholder: "Email",
          img: {},
        },
        {
          element: "input",
          type: "password",
          id: "lf-password",
          name: "lf-password",
          value: "",
          onChange: ,
          placeholder: "Password",
          img: {},
        },
        {
          element: "checkbox",
          id: "lf-remember-me",
          name: "lf-remember-me",
          value: "lf-remember-me",
          onChange: ,
          display: "Remember Me",
          isSelected: false
        }
      ]
    }
  }

  // Figure out how to pass onChange functions per item in state.
  handleOnChangeEmail(e) {
     console.log("Email changed");
  }

  render() {
    return (
      <div className="LoginComponent">
        {/* 
            Create onSubmit function for submitting the form
            Create handle change functions for inputs
        */}
        <FormComponent id={ this.state.id } name={ this.state.name } onSubmit="" header={ this.state.header } items={ this.state.items } />
      </div>
    );
  }
}

export default LoginComponent;

Как видите, я хочу передать функцию handle в состоянии компонента, чтобы я мог однозначно обрабатывать входные данные формы.Когда я запускаю этот код, хотя он не работает, потому что я не могу передать функцию в состоянии.Разрешен ли этот тип запроса или он может быть выполнен другим способом?

Я знаю, что вы можете напрямую передать связанную функцию компоненту, но компонент формы динамически создается на основе массива state.item.

Вот мой компонент формы

import React from "react";
import './FormComponent.css';

import InputComponent from './InputComponent/InputComponent';
import FormHeaderComponent from './FormHeaderComponent/FormHeaderComponent';
import CheckboxComponent from "./CheckboxComponent/CheckboxComponent";

class FormComponent extends React.Component {
  render() {
    const formItems = this.props.items.map((item) => {
      switch(item.element) {
        case "input":
          return <InputComponent type={ item.type } id={ item.id } name={ item.name } placeholder={ item.placeholder } value={ item.value } onChange={ item.onChange } />
        case "checkbox":
          return <CheckboxComponent id={ item.id } name={ item.name } value={ item.value } selected={ item.isSelected } onChange={ item.onChange } display={ item.display } />
        default:
          return <InputComponent />;
      }
    });

    return (
        <form id={ this.props.id } name={ this.props.name }>
            <FormHeaderComponent header={ this.props.header } />

            {/* 
              Setup handling of submit functions
              Setup handling of onchange function for inputs
            */}

            { formItems }
        </form>
    );
  }
}

export default FormComponent;

Как вы можете видеть в formItems, я пытаюсь создать элементы с помощью функции onChange из переданного состояния. Любая помощь или предложения приветствуются.Я также знаю, что могу просто сделать компонент формы компонентом, который загружает все переданные потомки, так что вы в основном строите форму в компоненте входа без состояния, но я бы предпочел, чтобы это было не так.

Ответы [ 2 ]

1 голос
/ 18 апреля 2019

Попробуйте реализовать ту же функцию handleChange для обработки всех изменений значения формы.

Реагирует аргумент события передачи функции onChange. С аргументом события выполните необходимую логику. Не нужен ключ onChange в объекте формы в состоянии.

 
 // use lodash library for array handling. 
 // yarn add lodash
 // import {indexOf} from "lodash"
 // using fat arrow will save from binding function in constructor.
 handleChange=({target})=> {
     const {items} = this.state;
     // target.name/id will give the element state can be update as required. 
     let index = indexOf(items, {name:target.name})
     items[index].value = target.value;
     this.setState({
       items
     })
  }

// remove handle change from items and just user it for all form value change.
<FormComponent id={ this.state.id } name={ this.state.name } handleChange={this.handleChange} onSubmit="" header={ this.state.header } items={ this.state.items } />
1 голос
/ 18 апреля 2019

Хранение методов в состоянии, которое будет передано детям, обычно плохая идея.Я предлагаю альтернативу.

Рассмотрим функцию onChange, которая все еще будет находиться в LoginComponent и будет передана в качестве опоры <FormComponent />

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

LoginComponent:

  handleOnChangeEmail(e) {
    const { name, value } = e.target;
    console.log(`${name} changed to ${value}`);
  }

  render() {
    return (
      <div className="LoginComponent">
        <FormComponent
          id={this.state.id}
          name={this.state.name}
          onSubmit=""
          header={this.state.header}
          items={this.state.items}
          formOnChange={this.handleOnChangeEmail}
        />
      </div>
    );
  }

Затем, когда вы перебираете и создаете InputComponent, передайте его в onChange:

FormComponent:

class FormComponent extends React.Component {
  render() {
    const formItems = this.props.items.map(item => {
      switch (item.element) {
        case "input":
          return (
            <InputComponent
              type={item.type}
              id={item.id}
              name={item.name}
              placeholder={item.placeholder}
              value={item.value}
              onChange={this.props.formOnChange}
            />
          );
        case "checkbox":
          return (
            <CheckboxComponent
              id={item.id}
              name={item.name}
              value={item.value}
              selected={item.isSelected}
              onChange={this.props.formOnChange}
              display={item.display}
            />
          );
        default:
          return <InputComponent />;
      }
    });

    return (
      <form id={this.props.id} name={this.props.name}>
        <FormHeaderComponent header={this.props.header} />
        {formItems}
      </form>
    );
  }
}

PS: не забудьте bindваши функции или использовать функции стрелок.

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