React - 子组件可以将值发送回父表单吗 [英] React - Can A Child Component Send Value Back To Parent Form

查看:24
本文介绍了React - 子组件可以将值发送回父表单吗的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

InputField &Button 是进入表单以创建表单的自定义组件.我的问题是如何将数据发送回表单,以便在单击按钮时,我可以使用数据(用户名和密码)在表单上触发 ajax:

导出默认的auth.authApi(类 SignUpViaEmail 扩展组件{构造函数(道具){超级(道具);this.state = {电子邮件 : "",密码 : ""};this.storeEmail = this.storeEmail.bind( this );this.storePassword = this.storePassword.bind( this );}storeEmail(e){this.setState({ email : e.target.value });}商店密码(e){this.setState({ 密码: e.target.value });}句柄注册(){this.props.handleSignUp(this.state);}使成为(){返回(<div className="pageContainer"><form action="" method="post"><InputField labelClass = "标签"labelText = "用户名"inputId = "signUp_username"inputType = "email"inputPlaceholder = "注册邮箱"inputClass = "输入"/><按钮 btnClass = "btnClass"btnLabel = "提交"onClickEvent = { handleSignUp }/></表单>

);}});

或者不推荐&我不应该在表单中创建自定义子组件吗?

子组件 => InputField

导入反应,{ 组件 } 来自反应";导出类 InputField 扩展组件{构造函数(道具){超级(道具);this.state = {价值 : ""};this.onUserInput = this.onUserInput.bind( this );}onUserInput(e){this.setState({ value : e.target.value });this.props.storeInParentState({[ this.props.inputType ] : e.target.value });}使成为(){return 

<label htmlFor = {this.props.inputId}className = {this.props.labelClass}>{this.props.labelText}<输入id = {this.props.inputId}类型 = {this.props.inputType}onChange = {this.onUserInput}/><span className = {this.props.validationClass}>{ this.props.validationNotice }</span>

;}}

错误:我在父 storeEmail 函数上收到错误 e.target is undefined.

解决方案

React 的单向数据绑定模型意味着子组件不能将值发送回父组件除非明确允许这样做.React 这样做的方法是将回调传递给子组件(参见 Facebook 的 "表格"指南).

class Parent extends Component {构造函数(){this.state = {价值: ''};}//...handleChangeValue = 事件 =>this.setState({value: event.target.value});//...使成为() {返回 (<孩子值={this.state.value}onChangeValue={this.handleChangeValue}/>);}}类子扩展组件{//...使成为() {返回 (<输入类型=文本"值={this.props.value}onChange={this.props.onChangeValue}/>);}}

注意父组件处理状态,子组件只处理显示.Facebook 的提升状态"指南是学习如何做到这一点的好资源.

这样,所有数据都存在于父组件中(在状态中),而子组件只能更新该数据(回调作为 props 传递).现在您的问题解决了:您的父组件可以访问它需要的所有数据(因为数据存储在状态中),但是您的子组件负责将数据绑定到它们自己的各个元素,例如 <input> 标签.


附录

回应此评论:

<块引用>

如果我们渲染一个子组件的列表怎么办?在提升状态技术中使用这个单一的事实来源会让父级控制所有子级输入的所有状态,对吗?那么我们如何才能从父组件访问子组件中的每个值输入(呈现为列表)?

对于这种情况,您可以为列表中的每个元素映射一个子组件.例如:

class Parent extends Component {//...handleChangeListValue = 索引 =>事件 =>{this.setState({列表:this.state.list.map((element, i) => i === index ? event.target.value : element)});}//...使成为() {返回 this.state.list.map((element, i) => (<孩子值={元素}onChangeValue={this.handleChangeListValue(i)}/>));

P.S. 免责声明:以上代码示例仅用于说明所讨论的概念(提升状态),并反映回答时 React 代码的状态.关于代码的其他问题,例如不可变与可变数组更新、静态与动态生成的函数、有状态与纯组件以及基于类与基于钩子的有状态组件,最好将其作为一个单独的问题提出.

The InputField & Button are custom components that go into a form to create a form. My issue is how do I send the data back up to form so that on button click, I can fire ajax on the form with data (username & password):

export default auth.authApi(
  class SignUpViaEmail extends Component{

    constructor(props){
      super(props);
      this.state = {
        email : "",
        password : ""
      };
      this.storeEmail = this.storeEmail.bind( this );
      this.storePassword = this.storePassword.bind( this );
    }

    storeEmail(e){
      this.setState({ email : e.target.value });
    }

    storePassword(e){
      this.setState({ password : e.target.value });
    }

    handleSignUp(){
      this.props.handleSignUp(this.state);
    }

    render(){
      return(
        <div className="pageContainer">

          <form action="" method="post">
            <InputField labelClass = "label"
                        labelText = "Username"
                        inputId = "signUp_username"
                        inputType = "email"
                        inputPlaceholder = "registered email"
                        inputClass = "input" />
            <Button btnClass = "btnClass"
                    btnLabel = "Submit"
                    onClickEvent = { handleSignUp } />
          </form>
        </div>
      );
    }

  }
);

Or Is it not recommended & I should not create custom child components within the form?

child component => InputField

import React,
       { Component } from "react";

export class InputField extends Component{

  constructor( props ){
    super( props );
    this.state = {
      value : ""
    };
    this.onUserInput = this.onUserInput.bind( this );
  }

  onUserInput( e ){
    this.setState({ value : e.target.value });
    this.props.storeInParentState({[ this.props.inputType ] : e.target.value });
  }

  render(){
    return  <div className = "">
              <label htmlFor = {this.props.inputId}
                     className = {this.props.labelClass}>
                {this.props.labelText}
              </label>
              <input id = {this.props.inputId}
                     type = {this.props.inputType}
                     onChange = {this.onUserInput} />
              <span className = {this.props.validationClass}>
                { this.props.validationNotice }
              </span>
            </div>;
  }
}

Error : I get the error e.target is undefined on the parent storeEmail func.

解决方案

React's one-way data-binding model means that child components cannot send back values to parent components unless explicitly allowed to do so. The React way of doing this is to pass down a callback to the child component (see Facebook's "Forms" guide).

class Parent extends Component {
  constructor() {
    this.state = {
      value: ''
    };
  }
  
  //...
  
  handleChangeValue = event => this.setState({value: event.target.value});
  
  //...
  
  render() {
    return (
      <Child
        value={this.state.value}
        onChangeValue={this.handleChangeValue}
      />
    );
  }
}

class Child extends Component {
  //...
  
  render() {
    return (
      <input
        type="text"
        value={this.props.value}
        onChange={this.props.onChangeValue}
      />
    );
  }
}

Take note that the parent component handles the state, while the child component only handles displaying. Facebook's "Lifting State Up" guide is a good resource for learning how to do this.

This way, all data lives within the parent component (in state), and child components are only given a way to update that data (callbacks passed down as props). Now your problem is resolved: your parent component has access to all the data it needs (since the data is stored in state), but your child components are in charge of binding the data to their own individual elements, such as <input> tags.


Addendum

In response to this comment:

What if we render a list of the child component? Using this single source of truth in Lifting state up technique will let the parent controls all the state of all the child inputs right? So how can we access each of the value input in the child component to (which is rendered as list) from the parent component?

For this case, you may map a child component for each element in the list. For example:

class Parent extends Component {
  //...
  handleChangeListValue = index => event => {
    this.setState({
      list: this.state.list
        .map((element, i) => i === index ? event.target.value : element)
    });
  }
  //...
  render() {
    return this.state.list.map((element, i) => (
      <Child
        value={element}
        onChangeValue={this.handleChangeListValue(i)}
      />
    ));

P.S. Disclaimer: above code examples are only for illustrative purposes of the concept in question (Lifting State Up), and reflect the state of React code at the time of answering. Other questions about the code such as immutable vs mutable array updates, static vs dynamically generated functions, stateful vs pure components, and class-based vs hooks-based stateful components are better off asked as a separate question altogether.

这篇关于React - 子组件可以将值发送回父表单吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆