React 踩坑--input中的value与defaultValue

摘要:
简而言之,受控组件由React管理,而非受控组件的值由本地DOM管理。例如,不受控制的组件如下所示:此defaultValue实际上是本机DOM中的value属性。但是,在触发onChange事件后。setState会导致重新渲染。同时,React将优化渲染过程。事实上,它仍然通过设置输入值来实现。对于受控组件,输入值始终由React状态驱动。因此,回到我代码中的问题,解决方案是将defaultValue更改为value={this.state.XXX},然后在外部编写handleXXX函数,通过setState控制value的值。

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

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

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

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

如图所示:

React 踩坑--input中的value与defaultValue第1张React 踩坑--input中的value与defaultValue第2张

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

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

React 踩坑--input中的value与defaultValue第3张

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

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

React 踩坑--input中的value与defaultValue第4张

但当我在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的值。

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

React 踩坑--input中的value与defaultValue第5张

免责声明:文章转载自《React 踩坑--input中的value与defaultValue》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇并发编程-线程池(二)线程池回收线程Spark(二)—— 标签计算、用户画像应用下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Bootstrap文件上传插件File Input的使用

1、文件上传插件File Input介绍 这个插件主页地址是:http://plugins.krajee.com/file-input,可以从这里看到很多Demo的代码展示:http://plugins.krajee.com/file-basic-usage-demo。 这是一个增强的 HTML5 文件输入控件,是一个 Bootstrap 3.x 的扩展,...

解决JS(Vue)input[type='file'] change事件无法上传相同文件的问题

一般的解决方法:Html <input id="file" type="file" onchange="upload()" /> JS 事件逻辑执行完之后执行: document.getElementById('file').value = null; Vue中 <input ref="referenceUpload" @change=...

不难懂--------react笔记

  在jsx中不能使用class定义类名   因为class在js中是用来定义类的  定义类名的时候用className       label中的for必须写成htmlFor         ReactDOM.render:             参数1:需要渲染的dom元素或者组件         参数2:需要将渲染好的元素挂载在哪个挂载点身上...

layui 解决浏览器自动填充form表单账号和密码输入框的问题

用js去清除input的value值是无效的,因为浏览器填充账号密码的动作是在js执行完之后发生的。 浏览器会自动寻找第一个输入框和最后一个密码框自动填充,我们可以给它添加一些假的密码框,让其无法自动填充。 解决办法: 在自己的input框前后添加假的<input type="password" /> <input type="pass...

Django:使用模态框新增数据,成功后提示“提交成功”,并刷新表格bootstrap-table数据

废话不说先看图:    代码实现:   前台代码: {% load staticfiles %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>项目...

Reactv16.8.6生命周期函数

组件生命周期函数 React 主动调用的方法,也可重写这些方法 生命周期图谱 当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下: constructor(props) 如果不需要初始化 state 或 不进行方法绑定,则不需要使用该方法 在组件挂载之前会先调用该方法,在实现构造函数时必须先调用super(props)方法,否则会出现BUG通常,...