踩过React表单的坑后有感

如题所示,最近捣鼓React表单踩坑了,才捣鼓没多少时日,心就变浮躁了,开始看不下去文档,也不谷歌百度直接开码,然后就是各种报错,越报错心越急越得不到解决心情越差,好不容易静下心来搜集资料准备搞定表单,这里先记下来,以备不时只需!

踩过的坑…

直接开写吧:

input标签忘记闭合导致报错

1
2
3
4
5
6
var SimpleComp = React.createClass({
render(){
return <input type="text" placeholder="随便输入点什么吧!">
}
});
ReactDOM.render(<SimpleComp />, document.body)

运行上面的这段代码,发现并页面渲染异常,打开浏览器console一看,下面的出现了错误,并且是下面这样的:

报错图片

清清楚楚明明白白,标签并没有闭合,并且直指9行行最后渲染出了问题,然后我就一直找一直找,没错误啊,可始终还是报错
最后经过各种尝试才知道,input标签要强制闭合的,不然就会转换错误
知道真相的我眼泪掉下来,原来是这么回事啊,平时html写得飞起,细节这些什么的,都没注意哎!
再有,控制台上打印的异常和错误可千万别轻信,以前已经在这个被坑过了

受控与不受控

有过React基础的童鞋都知道,React内部通过props和state来传递属性和状态,其中属性经由组件外属性传入,作用于组件后无法改变
state 产生于组件内部, 通过setState()来改变状态,每一次改变状态,组件将会被重绘
对于表单来说,props和state用得都很频繁,所以在这里提及一下

先来看非受控组件吧,顾名思义就是组件的状态不受控制,从代码上体现出来的就是,一个input不含有value属性

1
2
3
4
5
6
var NotControlComp = React.createClass({
render() {
return <input type="text" defaultValue={this.props.placeholder}/>
}
});
ReactDOM.render(<NotControlComp placeholder='随便输入点什么吧!' />, document.body)

上面的一段代码定义了一个非受控的input,接受用户的输入而改变状态
注意:这里使用到的defaultValue属性作用类似于placeholder属性

好吧,事实上我们使用非受控组件的情况比较多,我们会监听input的onChange时间,通过state来更新状态
下面是一个简单的获取用户输入的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var ExampleComp = React.createClass({
getDefaultProps(){
return{placeholder: '输入吧'}
},
getInitialState(){
return{
val: ''
}
},
handleChange(e){
this.setState({val: e.target.value})
},
render(){
return(
<div>
<input type="text" defaultValue={this.props.val} onChange={this.handleChange}/>
<p>你输入了:{this.state.val}</p>
</div>
)
}
});
ReactDOM.render(<ExampleComp placeholder='随便输入点什么吧!' />, document.body)

那么受控组件就很显而易见了,受控的input定义了一个value属性,并且value部位null

1
2
3
4
5
6
var ControlComp = React.createClass({
render(){
return <input type="text" value="不要尝试修改这个值啦!" />
}
});
ReactDOM.render(<ControlComp />, document.getElementById('app'))

好了,最简单的受控组件就写好了,当你尝试去修改表单中的值的时候,发现根本无法修改
这点明显和我们平时写html不一样,同样的input标签在html中就可以修改但是到了react中就没办法修改了,想过原因吗?
官方文档中给出了答案: 不比HTML,React组件必须在任何时间点呈现视图的状态而不仅仅是在初始化的时候, 好好理解!

其他

  1. 不要通过添加子节点的方式给<textarea>添加内容,应该使用defaultValue或者value属性,避免产生歧义,因为JSX本身就是javascript

  2. 你可以通过selected属性来选中一个下拉栏, 但是为了组件的可操作性,请使用value 或者 defaultValue来代替就像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var SelectComp = React.createClass({
    render(){
    return(
    <select value='B'>
    <option value='A'>A</option>
    <option value='B'>A</option>
    <option value='C'>A</option>
    </select>
    )
    }
    });
    ReactDOM.render(<SelectComp />, document.body)

    想要非受控组件的话,就使用defaultValue属性好了
    当然了,可以通过传入一个数组来达到多选的目的, 前提是给select添加multiple={true}就可以了

看到这里,也许有人心里还有疑问,受控的组件既然不能修改那到底该怎么用?
对于这个问题,请看下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var ControlComp = React.createClass({
getInitialState(){
return{value: 0}
},
handleClick(e){

this.setState({value: this.state.value + 1})
},
render(){
return (
<div>
<input type="text" value={this.state.value} />
<button onClick={this.handleClick}>+</button>
</div>
)
}
});
ReactDOM.render(<ControlComp />, document.body)

好了,我们添加了一个button来控制受控组件的值,当然还有很多方式,比如我们可以给受控组件添加一个onChange事件监听

好了,React表单的基本知识就说到这里,感谢那些曾经让我烦躁无比的坑!

分享到 评论