likes
comments
collection
share

一文讲清 React 表单中受控与非受控输入(译)你可能看到过很多文章都在说“你不应该使用 setState”,而文档上

作者站长头像
站长
· 阅读数 48

原文:Controlled and uncontrolled form inputs in React don't have to be complicated

一文讲清 React 表单中受控与非受控输入(译)你可能看到过很多文章都在说“你不应该使用 setState”,而文档上

你可能看到过很多文章都在说“你不应该使用 setState”,而文档上却说“refs是坏的”……这太矛盾了。很难理解如何“做对”,甚至是什么标准来选择。

你该怎么做表单呢?

毕竟,表单是很多网页应用程序的核心。然而,在React中处理表单似乎有点……基础?

别怕。让我向你展示这些方法之间的区别,以及什么时候应该使用每种方法。

非受控组件(The Uncontrolled)

非受控输入就像传统的HTML表单输入:

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

他们记住你输入的内容。你可以用ref来获取它们的值。例如,在按钮的onClick处理程序中:

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

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

换句话说,**你需要在需要的时候从字段中“提取”值。**这可以在表单提交时发生。

这是实现表单输入的最简单方法。当然,在现实世界中的简单表单和学习React时,这种方法是有效的。

不过它并不是那么强大,所以接下来让我们看看那些受控输入。

小结: 非受控组件不使用 state 而是使用简单有效的 ref ,仅从字段中提取值,适用于表单逻辑不复杂的情况。

受控组件

受控输入接受其当前值作为属性,并接受一个回调函数来更改该值。 可以说,这是更“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都会被调用。它接受输入的新值并将其设置在状态中。

一文讲清 React 表单中受控与非受控输入(译)你可能看到过很多文章都在说“你不应该使用 setState”,而文档上

  • 它开始是一个空字符串——''
  • 你输入ahandleNameChange获取到a并调用setState。然后输入被重新渲染,值为a
  • 你输入bhandleNameChange获取到值ab并设置到状态中。输入再次重新渲染,现在值为"ab"

这种流程“推送”值的变化到表单组件,因此表单组件总是有输入的当前值,而不需要明确的请求。

这意味着你的数据(状态)和UI(输入)总是同步的。状态赋予输入值,输入请求表单组件更改当前值。

这还意味着表单组件可以立即响应输入更改;例如,通过:

  • 即时反馈,如验证
  • 除非所有字段都有有效数据,否则禁用按钮
  • 强制要求特定输入格式,如信用卡号码

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

小结:受控组件定义 state 对值进行存储,其数据和 UI 同步,这让我们可以控制状态更新的逻辑,如添加校验等。

元素何时受控

当然还有其他表单元素。你有复选框、单选按钮、选择框和文本区域。

如果通过属性设置其值,表单元素就变成“受控”的。就是这样。

每个表单元素都有不同的属性来设置值,所以这里有一个小表格来总结:

元素值属性Change callback(回调)New value in the callback(回调中新值)
<input type="text" />value="string"onChangeevent.target.value
<input type="checkbox" />checked={boolean}onChangeevent.target.checked
<input type="radio" />checked={boolean}onChangeevent.target.checked
<textarea />value="string"onChangeevent.target.value
<select />value="option value"onChangeevent.target.value

结论

受控和非受控表单字段各有优势。评估你的具体情况并选择合适的方法——适合你的方法就是好方法。

如果你的表单在UI反馈方面非常简单,用ref的非受控方式完全没问题。你不必听信各种文章说什么是“坏的”。

特性非受控受控
一次性值检索(例如提交时)
提交时验证
即时字段验证
有条件地禁用提交按钮
强制输入格式
多个输入对应一个数据
动态输入

此外,这不是一次性的决定:你可以随时迁移到受控输入。从非受控到受控输入的迁移并不难。

转载自:https://juejin.cn/post/7422660569257213990
评论
请登录