【问题标题】:React - How to get state data from a child component?React - 如何从子组件获取状态数据?
【发布时间】:2020-01-29 13:51:56
【问题描述】:

我刚开始学习反应,我目前正在构建一个表单,到目前为止,我已经创建了一个父组件“表单”,并将其余输入作为组件分开,每个组件都有自己的状态.我的问题是如何从子组件中获取状态数据并在提交表单时在父组件“表单”中使用它?

这是我的父组件

import React, { Component } from "react";

import Name from "components/Name";
import Email from "components/Email";
import Select from "components/Select";
import Bio from "components/Bio";

class Form extends Component {
    handleSubmit = event => {
        event.preventDefault();
    };

    render() {
        return (
            <form onSubmit={this.handleSubmit}>
                <div className="shape rectangle"></div>
                <div className="shape triangle"></div>
                <div className="shape circle"></div>
                <Name />
                <Email />
                <Select />
                <Bio />
                <button type="submit" className="btn">
                    Submit
                </button>
            </form>
        );
    }
}

export default Form;

和子组件之一

import React, { Component } from "react";

// Create Name component for name && email inputs
class Name extends Component {
  constructor(props) {
    super(props);

    this.state = {
      firstName: "",
      lastName: ""
    };
  }

  // Handle first name input on change event
  handleFirstNameChange = event => {
    this.setState({
      firstName: event.target.value
    });
  };

  // Handle last name input on change event
  handleLastNameChange = event => {
    this.setState({
      lastName: event.target.value
    });
  };

  // Render labels and name inputs
  render() {
    const { firstName, lastName } = this.state;
    return (
      <div className="form-names">
        <label htmlFor="firstName">Name</label>
        <br/>
        <input
          type="text"
          name="firstName"
          value={firstName}
          placeholder="First Name"
          id="firstName"
          onChange={this.handleFirstNameChange}
        />
        <input
          type="text"
          name="lastName"
          value={lastName}
          placeholder="Last Name"
          id="lastName"
          onChange={this.handleLastNameChange}
        />
      </div>
    );
  }
}

export default Name;

【问题讨论】:

  • 把 state 和 onChange-listeners 放在 parent 中,并将它们作为 props 传递给 childs
  • 现在试试

标签: javascript reactjs forms


【解决方案1】:

要完成此操作,您需要将状态“提升”到一个公共父组件(称为祖先组件),在您的情况下,这将是 &lt;Form&gt; 组件。然后,您可以将值作为props 传递给每个相应的子组件。

看起来像这样:

import React, { Component } from "react";

import Name from "./Name";
// More imports go here..

class Form extends Component {
  state = {
    firstName: "",
    lastName: ""
  };

  handleSubmit = event => {
    event.preventDefault();
  };

  // Handle first name input on change event
  handleFirstNameChange = event => {
    this.setState({
      firstName: event.target.value
    });
  };

  // Handle last name input on change event
  handleLastNameChange = event => {
    this.setState({
      lastName: event.target.value
    });
  };

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <Name
          firstName={this.state.firstname}
          lastName={this.state.lastName}
          handleFirstNameChange={this.handleFirstNameChange}
          handleLastNameChange={this.handleLastNameChange}
        />
        {/* More components go here.. */}
        <p>Current state:</p>
        {JSON.stringify(this.state)}
      </form>
    );
  }
}

export default Form;

Working example

更多信息:来自 React 官方文档的Lifting state up

【讨论】:

    【解决方案2】:

    你可以在父组件中使用单个状态,并在props中传递名字和姓氏,你的代码会变成:

    import React, { Component } from "react";
    
    import Name from "components/Name";
    import Email from "components/Email";
    import Select from "components/Select";
    import Bio from "components/Bio";
    
    class Form extends Component {
      state = {
        firstName: '',
        lastName: '',
      }
    
      onChange = (e) => {
      this.setState({[e.target.name] : e.target.value})
      }
    
      handleSubmit = event => {
       event.preventDefault()
      }
    
      render() {
        return (
            ...
            <Name onChange={this.onChange} firstName={this.state.firstName} lastName={this.state.lastName} />
            ...
            <button type="submit" className="btn">
              Submit
            </button>
           </form>
        )
      }
    }
    
    export default Form;
    

    你的子组件变成了:

    import React, { Component } from "react";
    
    // Create Name component for name && email inputs
    class Name extends Component {
    
    
      render() {
        const { firstName, lastName , onChange} = this.props;
        return (
          <div className="form-names">
            <label htmlFor="firstName">Name</label>
            <br/>
            <input
              type="text"
              name="firstName"
              value={firstName}
              placeholder="First Name"
              id="firstName"
              onChange={onChange}
            />
            <input
              type="text"
              name="lastName"
              value={lastName}
              placeholder="Last Name"
              id="lastName"
              onChange={onChange}
            />
          </div>
        );
      }
    }
    
    export default Name;
    

    【讨论】:

      【解决方案3】:

      我的想法是像下面这样,将数据作为道具传递给组件。但这对我来说没有意义,因为当您单击提交按钮时,表单会从父组件收集数据。最好将表单保留在父组件中,并将所有输入数据分组。

      import React, { Component } from "react";
      
      import Name from "components/Name";
      import Email from "components/Email";
      import Select from "components/Select";
      import Bio from "components/Bio";
      
      class Form extends Component {
          constructor(props){
            super(props)
            this.state = {
              firstName = "",
              lastName = "",
              (and other input data you need)...
            }
          }
      
          handleSubmit = event => {
              event.preventDefault();
          };
      
          render() {
              return (
                  <form onSubmit={this.handleSubmit}>
                      <div className="shape rectangle"></div>
                      <div className="shape triangle"></div>
                      <div className="shape circle"></div>
                      <Name firstName={this.state.firstName} lastName={this.state.lastName}/>
                      <Email (inputData as props)/>
                      <Select (inputData as props)/>
                      <Bio (inputData as props)/>
                      <button type="submit" className="btn">
                          Submit
                      </button>
                  </form>
              );
          }
      }
      
      export default Form;
      

      【讨论】:

        【解决方案4】:

        您可以使用 ContextRedux 之类的东西,这将允许您创建通用存储并从任何组件中检索状态在您的父组件中创建方法,将它们传递下来到它的孩子,并从该子组件中调用它们。例如,您可以在Form 中拥有handleFirstNameChange 并将其传递给Name。这样做时,您现在可以将 name 之类的道具保留在 Form 中,并将其传递下去。

        【讨论】:

        • 我的react知识还是很基础的,对context和redux都不熟悉
        • 如果你还是 React 新手,它们是非常深刻的概念,需要全面掌握。如果您有兴趣,我会阅读它们,看看它们是否适合您的需求。同时,我只是传递我从父级描述的道具,让您基本了解层次结构的概念在这个库中是如何工作的。
        猜你喜欢
        • 1970-01-01
        • 2020-11-18
        • 1970-01-01
        • 2018-09-13
        • 2020-09-25
        • 1970-01-01
        • 2020-08-19
        • 1970-01-01
        • 2019-05-17
        相关资源
        最近更新 更多