通过状态传递onChange事件

时间:2019-04-18 04:20:49

标签: javascript reactjs components

我正在创建一个表单组件,并且希望能够传递每个表单元素的更改元素,而我似乎无法使其正常工作。

我有我的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 个答案:

答案 0 :(得分:1)

在状态中存储要传递给孩子的方法通常不是一个好主意。我提议一种替代方法。

考虑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您的功能或使用箭头功能。

答案 1 :(得分:1)

尝试实现相同的功能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 } />