【问题标题】:Pass down onChange to child component in react在反应中将 onChange 传递给子组件
【发布时间】:2018-07-21 17:42:26
【问题描述】:

我有一个 react 组件,我想将 onChange 作为 prop 传递给子组件,我正在使用原子设计,这是我的代码:

HeadComponent.js

class Headcomponent extends React.Component{

  constructor (props) {

    super(props);
    this.state = {
      email: '',
      password: '',
      formErrors: {email: '', password: ''},
      emailValid: false,
      passwordValid: false,
      formValid: false,
      items: [],

    }
  }

  handleUserInput = (e) => {

    const name = e.target.name;
    const value = e.target.value;
    this.setState({[name]: value},
                  () => { this.validateField(name, value) });
  }

render(){

    const fields= [
    {
      label: 'hhdghghd',
      placeholder: 'fhfhhfhh 1',
      ExampleMessage: this.state.formErrors.email ,
      ErrorMessage: 'error message for input 1',
      inputValue: this.state.email,
      onChange: this.handleUserInput  //this is where I'm passing my function


    },
    {
      label: 'fffff',
      placeholder: 'tttttt 2',
      ExampleMessage: 'example message  for second label',
      ErrorMessage: 'error message for input 2',
      onChange: this.handleUserInput


    },
  ]

return (
    <div>

  <Form fields={fields} buttonText="Submit"/>

    </div>
        );
    }

}

export default Headcomponent;

Form.js

    const Form = props => (
      <form className="Form">
        {
          props.fields.map((field, i) => (<LabeledInput label={field.label}
           placeholder={field.placeholder}
           ExampleMessage={field.ExampleMessage}
           ErrorMessage={field.ErrorMessage}
           onChange= {(e)=> field.onChange}
           inputValue= {field.inputValue}
           key={i}
           passwordError={props.passwordError}

           />))
        }
        <Button text={props.buttonText} />
      </form>
    );

    Form.propTypes = {
      fields: PropTypes.arrayOf(PropTypes.object).isRequired,
      buttonText: PropTypes.string.isRequired,
    };

    export default Form;

标签输入

const LabeledInput = props => (
  <div className={`form-group `} >
    <Label text={props.label} />
    <Input inputValue={props.inputValue} placeholder={props.placeholder} type="text" onChange={(e)=> props.onChange} />

    <ErrorMessage text={props.ErrorMessage} />
    <ExampleMessage ExampleMessage={ props.ExampleMessage} />
  </div>
);

LabeledInput.propTypes = {
  label: PropTypes.string.isRequired,
  placeholder: PropTypes.string,
  onChange: PropTypes.func.isRequired,
  //value: PropTypes.string.isRequired,
  exampleText: PropTypes.string,
};
export default LabeledInput;

Input.js

const Input = props => (
  <input type={props.type} class="form-control form-control-success is-valid" placeholder={props.placeholder} value={props.inputValue} className="form-control form-control-success"
      onChange={ (e)=> props.onChange } />
);

Input.propTypes = {

  inputValue: PropTypes.string,
  type: PropTypes.string,
  placeholder: PropTypes.string,
  onChange: PropTypes.func.isRequired,
};

export default Input;

如何将handleUserInputHeadComponent.js 传递到Input.js,到目前为止,使用道具我无法在更改文本时触发它。

【问题讨论】:

    标签: javascript reactjs ecmascript-6 react-props


    【解决方案1】:

    你忘了实际调用field.onChange 方法。而不是:

    onChange= {(e)=> field.onChange}
    

    你可以改成:

    onChange= {field.onChange}
    

    我还注意到您的handleUserInput 将状态设置为:

    { [name]: e.target.value }
    

    但是,您没有将name 设置为任何输入,这是行不通的。

    请看一下我的工作示例:

    const LabeledInput = props => (
      <div className="form-group">
        <label>{props.label}</label>
        <input
          className="form-control"
          type="text"
          placeholder={props.placeholder}
          onChange={props.onChange} // That's how you have to call onChange
          name={props.name} // You are not setting this prop
        />
        <div>{props.ErrorMessage}</div>
        <div>{props.ExampleMessage}</div>
      </div>
    )
    
    const Form = ({ buttonText, fields }) => (
      <form className="Form">
        {fields.map((field, i) => <LabeledInput key={i} {...field} />)}
        <button className="btn btn-primary">{buttonText}</button>
      </form>
    )
    
    class Headcomponent extends React.Component {
      constructor() {
        super()
    
        this.state = {
          email: '',
          password: '',
          formErrors: {email: '', password: ''},
          emailValid: false,
          passwordValid: false,
          formValid: false,
          items: [],
        }
    
        this.handleUserInput = this.handleUserInput.bind(this)
      }
      
      handleUserInput(e) {
        const name = e.target.name
        const value = e.target.value
        // Now that you have `name` and `value`, state updates are going to work
        this.setState({
          [name]: value
        })
      }
    
      render() {
        const fields = [
          {
            label: 'Email',
            placeholder: 'email placeholder',
            ExampleMessage: this.state.formErrors.email ,
            ErrorMessage: 'error message for input 1',
            inputValue: this.state.email,
            onChange: this.handleUserInput,
            name: 'email',
          },
          {
            label: 'Password',
            placeholder: 'password placeholder',
            ExampleMessage: 'example message  for second label',
            ErrorMessage: 'error message for input 2',
            onChange: this.handleUserInput,
            name: 'password',
          },
        ]
        
        return (
          <div>
            <Form fields={fields} buttonText="Submit"/>
            
            <div style={{ marginTop: 20 }}>
              <div>state.email: {this.state.email}</div>
              <div>state.password: {this.state.password}</div>
            </div>
          </div>
        )
      }
    }
    
    ReactDOM.render(
      <Headcomponent />,
      document.getElementById('root')
    )
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <div id="root"></div>

    【讨论】:

    • 我会投票给第二个选项,因为第一个选项最终会在每个渲染上创建新函数。另外,他在 Input.js 和 Form.js 上也有同样的问题。 :)
    • 仍然是相同的行为,我也不知道您是否注意到,但我将函数向下传递了多个级别,其想法是 Input.js 是最终应该触发该函数的组件。
    • 是的,把这个:onChange={ (e)=> props.onChange } 也改成 -> onChange={props.onChange}
    • @GherbiHicham 你是否也改变了在Input 组件中触发onChange 的方式?
    • 是的,我将它应用于所有子组件,但仍然没有
    猜你喜欢
    • 2019-01-02
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    • 2020-10-26
    • 1970-01-01
    • 2020-03-26
    相关资源
    最近更新 更多