state
React官方建议把State当做是不可变对象,State中包含的所有状态都应该是不可变对象,当State中的某个状态发生变化,我们应该重新创建这个状态对象,而不是直接修改原来的状态。State根据状态类型可以分为三种。
- 数字,字符串,布尔值,null,undefined这五种不可变类型。因为其本身就是不可变的,如果要修改状态的话,直接赋新值就可以,例如:
this.setState({
num: 1,
string: 'hello',
ready: true
});
- 数组
例如修改students数组的状态应该保证不会修改原来的状态,新增一个数组元素,应使用数组的concat方法或ES6的数组扩展语法。
let students = this.state.students;
this.setState({
students: students.concat(['xiaoming'])
});
//或者
this.setState(preState => ({
students: [ ...preState.books, 'xiaogang']
});
- 对象
对象也是可变类型,修改对象类型的状态时,应该保证不会修改原来的状态。可以使用ES6的Object.assign方法或者对象扩展语法。
//Object.assign方法
this.setState(preState => ({
school: Object.assign({}, preState.school, {classNum: 10})
}));
//对象扩展语法
let school = this.state.school;
this.setState({
school: { ...school, { classNum: 10 } }
})
函数式组件
无状态组件,自身没有状态,不需要管理state,是从props传入。
纯组件
当组件的props或者state发生变化的时候React会对组件当前的Props和State分别与nextProps和nextState进行比较,当发现变化时,就会对当前组件以及子组件进行重新渲染,否则就不渲染。有时候我们会使用shouldUpdateComponent来避免不必要的渲染。当然有时候这种简单的判断,显得有些多余和样板化,于是react就提供了PureComponent来自动帮我们完成这件事,简化了我们的代码,提高了性能。
组件
Component需要开发者显示定义shouldUpdateComponent且定制性更强。对于一些无论怎么修改都不应该让组件重新渲染的props就不必在shouldUpdateComponent中进行比较。同PureComponent一样Component中的state也应该是不可变对象。
为什么直接修改this.state无效
setState本质是通过一个队列机制实现state更新的。 执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时对状态队列进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。
React 的更新生命周期函数4个函数
- shouldComponentUpdate(被调用时this.state没有更新;如果返回了false,生命周期被中断,虽然不调用之后的函数了,但是state仍然会被更新)
- componentWillUpdate(被调用时this.state没有更新)
- render(被调用时this.state得到更新)
- componentDidUpdate
使用setState注意事项
setState在合成事件(onClick、onChange)和钩子函数中是异步的,在原生事件和setTimeout中都是同步的。setState方法有两个参数,第一个是对象,第二个是回调函数,可以通过第二个参数setState(object,callback)中的callback拿到更新后的结果。