react 受控表单必须初始化
react 受控表单必须初始化
场景
这些天在学习 React
的时候遇到了一个奇怪的问题,明明受控表单的双向绑定已经成功了,然而控制台还是会出现 react 的警告:
1 | Warning: A component is changing an uncontrolled input of type undefined to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. |
代码很简单,仅仅只是一个登录表单
1 | /** |
1 | import React, { Component } from 'react' |
在 App 组件的 constructor
中明明已经通过 new User()
初始化了 user
属性,然而在输入的时候,还是会出现警告。
注:此时在输入框中输入值,确实会影响到 react state 中的 user 属性,反之亦然。只有一点,当重置表单,即使用
this.setState({user: new User()})
重置 user 对象无法影响到页面上输入框的值。
此处出现了两个问题
- 为什么在输入的时候会出现警告
- 为什么重置之后输入框的值没有变化
解决
最终,吾辈在 StackOverflow 上找到了答案。
很重要的一句话:对于要控制的输入,其值必须与状态变量的值相对应。
最初并未满足这个条件,值为 null
的 state
属性会被 react
视为未定义,导致表单最初是不受控制的。但是,当 onChange
第一次被触发的时候,this.state.user.username
就被设置了。此时,满足了条件,从非受控表单转换为了受控表单并导致了控制台的警告。
同理,当使用 this.setState({user: new User()})
重置的时候,又变成了非受控表单,所以这里的绑定再次失效了。
注: react 使用
==
而非===
比较是否为null
,而null == undefined
的值为true
,所以。。。
那么,知道问题了之后,我们只要保证初始值 val != null
即可。
例如上面的代码可以修改 User.js
:
1 | /** |
那么,关于 react 中的受控表单初始化的问题便到此为止了。可想而知,react 的坑还有很多没有踩完呢