这是一本书的一个章节,有关 react form 中的受控组件和非受控组件,感谢作者。

原文链接:goshakkk.name/controlled-…

你可能已经看过很多文章说“你不应该使用 setState ”,而文档中声称“ refs 是不好的”……这是很矛盾的。很难理解如何“做到正确”,做选择的标准是什么。

到底应该怎样创建 form 呢?

毕竟,form 是很多 web 应用程序的核心,而在 React 中处理 form 似乎有一点基础。

不要怕,让我来想你展示这些方法的不同,以及你应该选择哪一种。

非受控的

非受控输入框就像传统的 HTML 输入框一样:

class Form extends Component {
  render() {
    return (
      <div>
        <input type="text" />
      </div>
    );
  }
}
复制代码

它们记录了你输入的信息,你可以使用 ref 获取它们的值。例如,在按钮的 onClick 处理中:

class Form extends Component {
  handleSubmitClick = () => {
    const name = this._name.value;
    // do something with `name`
  }

  render() {
    return (
      <div>
        <input type="text" ref={input => this._name = input} />
        <button onClick={this.handleSubmitClick}>Sign up</button>
      </div>
    );
  }
}
复制代码

换句话说,当你需要的时候你需要从表单域中“拉”表单值。当表单提交时这种情况会发生。

这是最简单的实现表单输入的方式,肯定会有这样使用的有效案例:在现实中处理简单的表单,还有学习 react 的时候。

然而他不够强大,所以我们看一下接下来这些受控的输入框。

受控的

一个受控输入框接收它的当前值作为一个属性,并且有一个回调来修改它的值。你可以说这是处理这件事的一种更“ React 的方式”(不代表你总是要使用这种方式)。

<input value={someValue} onChange={handleChange} />
复制代码

这是很好的……但是这个输入框的值必须要存在于某处的state中。通常,渲染输入框的组件(即表单组件)把它保存在它的state中:

class Form extends Component {
  constructor() {
    super();
    this.state = {
      name: '',
    };
  }

  handleNameChange = (event) => {
    this.setState({ name: event.target.value });
  };

  render() {
    return (
      <div>
        <input
          type="text"
          value={this.state.name}
          onChange={this.handleNameChange}
        />
      </div>
    );
  }
}
复制代码

(当然,它可以保存在另一个组件的状态中,甚至是独立的状态存储,例如 Redux

每次你输入一个新的字符,handleNameChange 被调用,他接收输入的新值并把它设置到 state 中。

  • 开始是一个空字符串——''
  • 输入一个a并且handleNameChange获取了一个a并调用setState。输入框接着重新渲染为拥有一个 value 为a
  • 输入bhandleNameChange获取到值ab并设置到 state 中,输入框再次重新渲染,现在带有属性value="ab"

这种流程把值的变化“推”给表单组件,因此Form组件始终拥有输入框的当前值,不需要明确地去要值。

这意味着你的数据( state )和 UI(输入框)总是同步的,state 提供值给输入框,输入框请求Form修改当前值。

这也意味着表单组件能够立刻响应输入框变化,例如:

但是如果你不需要这些并且认为非受控的会更简单,那就去吧。

什么使一个元素“受控”

当然,有其他的表单元素:复选框、单选框、下拉框、文本域。

如果通过一个 prop 来设置一个表单元素的 value ,它变为“受控的”,就这样。

每一个表单元素有不同的用来设置 value 的 prop ,下面是一个总结的小表格

Element Value property Change callback New value in the callback
<input type="text" /> value=”string” onChange event.target.value
<input type="checkbox" /> checked={boolean} onChange event.target.checked
<input type="radio" /> checked={boolean} onChange event.target.checked
<textarea /> value=”string” onChange event.target.value
<select /> value=”option value” onChange event.target.value

结论

受控和非受控表单字段都有它们的价值,评估具体的场景来选择方法——对你有用的就足够了。

如果你的表单在 UI 反馈方面特别简单,非受控的使用 refs 完全可以,你不必听各种文章说“不好”。

特性 非受控的 受控的
一次性取值(如:提交时) true true
提交时校验 true true
实时表单域校验 false true
按条件禁用提交按钮 false true
强制输入格式 false true
多输入框控制单个数据 false true
动态输入框 false true

而且,这不是一种一劳永逸的决定:你总是可以迁移到受控输入框。从非受控输入迁移到受控输入并不困难

最后,这是我的有关React中表单的文章的组织清单

参考文献


关于译者:第一次翻译文章,英语水平很差,表述不够优雅,有问题欢迎指正。

本文首发于掘金社区,转载请知悉本人,防止窃取附上个人小站,后续文章会同步。

GankRobot转载声明

原文出处:掘金前端

原文作者:fx109138

原文地址:https://juejin.im/post/5da17f915188254db41c4a25