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

标签 javascript reactjs ecmascript-6 components state

我是 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>
        );
    }
}

关于javascript - 在 React Form 无状态组件和全状态 Root 组件之间传递多个输入字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49072043/

相关文章:

javascript - 如何在PHP中使用Ajax使用警报消息框而不刷新页面?

javascript - 如何使用动态内容更新 Twitter 分享按钮 URL?

javascript - React 项目中的 ES6 循环依赖

javascript - 按日期排序并进行比较,在 React 中返回错误的顺序

javascript - 使用 map 将每隔一个字符转换为大写

javascript - JQuery - 禁用滚轮直到动画完成

javascript - 匹配表格列宽的文本框

unit-testing - ReactJS 中的 Enzyme 未定义组件/属性的测试

javascript - Todo like app中虚拟DOM的优势是什么

reactjs - 文本区域未填充默认值,而是在文本区域顶部显示值?