react中input的defaultValue和value属性

问题引入

以下是官方文档介绍受控表单组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
export default class Form extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
mobile: '',
addressDetail: ''
}
}
handleInputChange(event) {
let self = this;
let target = event.target;
let name = target.name;
self.setState({
[name]: target.value
});
if(self.props.onUpdate) self.props.onUpdate(self.state);
}
render() {
let self = this;
return (
<div className="form-input">
<div className="input-item">
<div className="input-label">收货人</div>
<div className="input-con">
<div className="input-wrap"><input className="txt-input" type="text" name="name" value={self.state.name} onChange={self.handleInputChange.bind(self)}/><i className="i-del"></i></div>
</div>
</div>
<div className="input-item">
<div className="input-label">手机号码</div>
<div className="input-con">
<input className="txt-input" type="text" value={self.state.mobile} name="mobile" onChange={self.handleInputChange.bind(self)}/>
</div>
</div>
<div className="input-item">
<div className="input-label">所在区域</div>
<div className="input-con">
<input className="txt-input" type="text" value={self.props.pcat}/>
<a href="javascript:void(0)" className="sel-addr" onClick={this.props.onInputArea.bind(this)}></a>
</div>
</div>
<div className="input-item">
<div className="input-label">详细地址</div>
<div className="input-con">
<textarea className="txt-textarea" value={self.state.addressDetail} name="addressDetail" onChange={self.handleInputChange.bind(self)}></textarea>
</div>
</div>
</div>
);
}
}

按照以上写法可以完成简单的表单输入,并提交数据,但是现在需要先给表单填上从父组件传过来的props的初始数据,马上想到defaultVaule对不对?思路是对的,但是当我修改成如下代码之后,视图并没有像我们意料中一样展示出来。

1
<input className="txt-input" type="text" defaultValue={self.props.editAddress.name} value={self.state.name} name="name" onChange={self.handleInputChange.bind(self)}/>

编译后的html如下,value里依然是空的,这并不是我想要的

1
<input type="text" class="txt-input" value="" name="name">

解决方案

实际上我被defaultValue带偏了,value里不是已经给了state吗?并且state就有默认值为空,所以在这里设置defaultValue并没有什么卵用。

value默认值就是props,那直接给value赋值props不就好了。

1
<input className="txt-input" type="text" value={self.props.editAddress.name} name="name" onChange={self.handleInputChange.bind(self)}/>

这样修改后,onChange事件就需要通过修改父组件的state值,来修改当前输入组件的value中props的值,如下更改:

  • 子组件
1
<input className="txt-input" type="text" value={self.props.editAddress.name} name="name" onChange={self.props.onUpdate.bind(self)}/>
  • 父组件
    1
    <Form onUpdate={self.updateAddress.bind(self)} pcat={self.state.pcat} onInputArea={self.openArea.bind(self)} editAddress={self.state.submitParams}/>

如上修改完成后,功能实现没问题了,但是控制台此时给了你一个警告,告诉你:

1
Warning: A component is changing an uncontrolled input of type text 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. More info: https://fb.me/react-controlled-components

警告大致意思就是说你现在是受控组件,但是这个组件是不需要受控的。所以你需要改成非受控组件,那么去看看官方非受控组件是咋写的,然后回来改改。改完如下:

  • 子组件
1
<input className="txt-input" type="text" value={self.props.editAddress.name||''} name="name" onChange={self.props.onUpdate.bind(self)}/>