React 踩坑--input中的value与defaultValue

这两个月实习期时间踩了不少坑,先来谈谈有代表性的一个。

我们知道表单是前端里很常见的一个东西,往往包含了很多数据校验逻辑。 

React、antd 对表单元素专门做了优化处理,有了一些抽象的东西,使得他们的使用方式更统一更规范。。

在一次需求开发中,有一块是这样的:首先渲染一个Table,里面每一项都有个“编辑”操作,点击弹出Modal框 

如图所示:

 

 

 

 

这个Modal框是一个表单,里面的文本框 下拉框等 都带有从Table里对应的那一项传来的默认值

于是我习惯性地想到了设置 “defaultValue”,如下图。。

但跑起来后发现这样一个问题:

第一次点开弹出框,他带的默认值是正确的:

 

但当我在Table里改变了此项数据再次点开,它并没有按照设想的显示改变后的选项,而是一直固定在“是”。

解决这个问题前,先来回顾一下React的 受控和非受控组件

 

“在 HTML 中,表单元素(如<input>、 <textarea> 和 <select>)之类的表单元素通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。” ——React docs

 

这里有一个新的概念叫“受控组件”。那么如何理解受控组件和非受控组件呢。

 

受控组件,简单的说,就是由React管理了它的value,而非受控组件的value就是原生的DOM管理的。 

他们的写法上也有很大区别。

例如,非受控组件这么写:

<input type="text" defaultValue="a" />

这个 defaultValue 其实就是原生DOM中的 value 属性。

这样写出的来的组件,其value值就是用户输入的内容,React完全不管、也管不到输入的过程。

 

而受控组件是这么写的:

<input type="text" value={this.state.name} onChange={this.handleChange} />
handleChange: function(e) {
  this.setState({name: e.target.value});
}

这里,value属性不再是一个写死的值,他是 this.state.name,而 this.state.name 是由 this.handleChange 负责管理的。 

这个时候实际上 input 的 value 根本不是用户输入的内容。而是onChange 事件触发之后,由于 this.setState 导致了一次重新渲染。

同时,React会优化这个渲染过程,实际上它仍然是通过设置input的value来实现的。

 

但一定要注意,受控组件显示的值和用户输入的值虽然很多时候是相同的,但他们根本是两码事。

受控组件显示的是 this.state.name 的值。你可以在handleChange中对用户输入的值做任意的处理,比如数据校验。

 

对比受控组件和非受控组件的输入流程:

 

  • 非受控组件: 用户输入A => input 中显示A
  • 受控组件: 用户输入A => 触发onChange事件 => handleChange 中设置 state.name = “A” => 渲染input使他的value变成A

 

正式因为这样,使得 React 的 state 成为唯一数据源。对于受控组件来说,输入的值始终由 React 的 state 驱动。

所以官方强烈推荐使用受控组件,因为它能更好的控制组件的生命流程。

 

所以回到我代码中的问题,解决办法就是:

defaultValue 改成 value={this.state.XXX},然后在外边写一个 handleXXX 函数,通过 setState 来控制value的值。

 

使之成为一个受控组件,这样就没问题了

posted @ 2020-09-09 00:23  墨西哥郊外的晚上*  阅读(4465)  评论(0编辑  收藏  举报