在React Form无状态组件和状态完全Root组件之间传递多个输入字段

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在React Form无状态组件和状态完全Root组件之间传递多个输入字段相关的知识,希望对你有一定的参考价值。

我是React的初学者,我正在尝试制作一个地址簿应用程序(目前仅限前端)。我在App.js文件中有我的根组件App,我正在尝试将表单元素从根组件移动到AddContact.js文件中的自己的组件(无状态)。当表单是表单提交处理函数的根组件的一部分时,我能够找到一种方法(搜索SO)来传递表单输入字段。但是当表单元素是不同组件的一部分时,我无法做同样的事情。下面是App.js和AddContact.js文件。我该怎么办呢?最好以最简单的方式,同时遵守react / es6最佳实践。

App.js

import React, { Component } from 'react';
import './App.css';
//import AddContact from './AddContact/AddContact';
//import './AddContact/AddContact.css';
import ContactList from './ContactList/ContactList.js';
import Cockpit from './Cockpit/Cockpit.js';


class App extends Component {
  state = {
    contacts:[]
  };

  addContactHandler = (event) => {
    event.preventDefault();
    //console.log(event.target[0].value);
    //console.log(event.target.name.value);
    const name = this.input1.value;
    const phone = this.input2.value;
    const email = this.input3.value;
    let contacts = [...this.state.contacts];
    if (name.length>0 && phone.length>0 && email.length>0){

      let contact = {
        name: name,
        phone: phone,
        email: email
      };
      contacts.push(contact);
      console.log("contacts: ", contacts);
      this.setState({
        contacts:contacts
      });
    }
    this.input1.value = '';
    this.input2.value = ''; 
    this.input3.value = '';

  };

  render() {
    let contactList = null;
    let contacts = [...this.state.contacts];
    if (contacts.length > 0) {
        contactList = (
          <ContactList
          contacts = {contacts}
          />
        );
    }
    return (
      <div className="App">
        <Cockpit/>
        <p>Add New Contact:</p>
        <form className="AddContact" onSubmit={(event)=>this.addContactHandler(event)}>
            <label>Name: 
                <input type="text" name="name" ref={(name) => {this.input1 = name}}/>
            </label>
            <label>Phone: 
                <input type="text" name="phone" ref={(phone) => {this.input2 = phone}}/>
            </label>
            <label>Email: 
                <input type="text" name="email" ref={(email) => {this.input3 = email}}/>
            </label>
            <input type="submit" value="Submit" />
        </form>
        {/* <AddContact submit={(event)=>this.addContactHandler(event)}/> */}
        {contactList}
      </div>
    );
  }
}

export default App;

AddContact.js

// Use at a later stage
import React from 'react';
import './AddContact.css';

const AddContact = (props) => {
    return (
        <div >
            <p>Add New Contact:</p>
            <form className="AddContact" onSubmit={props.submit}>
                <label>Name: 
                    <input type="text" ref={(name) => {this.input = name}}/>
                </label>
                <label>Phone: 
                    <input type="text" ref={(phone) => {this.input2 = phone}}/>
                </label>
                <label>Email: 
                    <input type="text" ref={(email) => {this.input3 = email}}/>
                </label>
                <input type="submit" value="Submit" />
            </form>
        </div>
    );
};

export default AddContact;
答案

将表单元素移动到其自己的专用组件中是一种很好的方法。但是不要尝试从父组件处理子组件的表单提交事件。子组件拥有该组件,它应该处理其突变和提交。考虑到这一点,这就是我构建组件的方式:

  1. 你的App渲染了AddContact组件。
  2. 对于你的AddContact组件,不要将onSubmit处理程序传递给它。相反,传递一个onAdd处理程序,它需要一个contact对象作为其参数。
  3. 让你的AddContact组件有状态!您是否有任何特殊原因希望它成为无国籍人?使其成为有状态,让它处理表单更新作为其状态的一部分(使用Controlled Components)。最后,在表单onSubmit事件中,打包一个contact对象并用它调用props.onAdd处理程序。

这将是一个更清洁,更合理分离的组件架构。父组件不应该担心子组件的表单提交行为,而应该期待一个包装得很好的contact对象。

看看这个:https://mn627xy99.codesandbox.io/

class AddContact extends React.Component {

    state = {
        name: "",
        phone: "",
        email: "",
    }

    submit = e => {
        e.preventDefault();
        this.props.onAdd(this.state);

        // Clear the form
        this.setState({name: "", phone: "", email: ""});
    }

    change = e => {
        e.preventDefault();
        this.setState({[e.currentTarget.name]: e.currentTarget.value});
    }

    render() {
        return (
            <div >
                <p>Add New Contact:</p>
                <form className="AddContact" onSubmit={this.submit}>
                    <label>Name: 
                        <input type="text" name="name" onChange={this.change} value={this.state.name} />
                    </label>
                    <label>Phone: 
                        <input type="text" name="phone" onChange={this.change} value={this.state.phone} />
                    </label>
                    <label>Email: 
                        <input type="text" name="email" onChange={this.change} value={this.state.email} />
                    </label>
                    <input type="submit" value="Submit" />
                </form>
            </div>
        );
    }
}

以上是关于在React Form无状态组件和状态完全Root组件之间传递多个输入字段的主要内容,如果未能解决你的问题,请参考以下文章

在 React 中分离有状态和无状态组件的线应该在哪里?

[react] 描述下在react中无状态组件和有状态组件的区别是什么?

无状态组件 React 路由器

React 组件从有状态到无状态(区别)

在 React 中,一个类组件可以是无状态的,而现在使用 Hooks 一个函数组件可以是有状态的吗?

[react] 在react中无状态组件有什么运用场景