概述
本文主要讨论下React中state的使用,以及setState的使用。
定义
state可以被视为React组件中的一个数据集合,这些数据用于记录组件中的可变状态,也就是说这些数据在组件中可以被修改。
那么,如何判断一个变量是否适合作为一个state中的数据?
组件对State的要求
在组件中,对于state数据,有着以下的要求:
- state能代表组件呈现的完整状态集:组件所有的状态改变,都能在state中体现出来
- state能代表组件呈现的最小状态集:state中的所有数据都体现组件的变化,没有多余的状态,也不需要通过其他状态计算来的中间状态
State与Props的区别
- state用于体现组件的变化,在当前组件中是可变的
- props从父级组件传入,在当前组件中是只读的
变量能否作为State的判据
所以,由上面的描述,我们可以从下面这几个方面判断一个变量是否可以作为state:
- 该变量是否由父级组件传入?若是,则不可用于state
- 该变量是否在组件整个生命周期内不变?若是,则不可用于state
- 该变量是否可以由其他state数据或props计算得到?若是,则不可用于state
- 该变量是否在render中用于渲染数据?若不是,则不可用于state
若变量不适用于作为state,则一般定义为组件的一个普通属性,即this.name
等变量。
State的更新
在React中。我们使用setState()
来进行state的更新,而不是直接更新state的状态。
// 错误的更新方法
this.state.name = '张三';
// 正确的更新方法
this.setState({name: '张三'});
状态更新可能是异步的
出于性能方面的考虑,React 可以将多个setState()
调用合并成一个调用来提高性能。
因此,this.state
可能是异步更新的,你不应该依靠它们的值来计算下一个状态。
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
this.setState({count: this.state.count + 1});
我们期待state中的count
增加了3次,但结果可能是增加了1次。
由于this.state
可能是异步更新,this.setState()
只是在反复设置同一个值而已,上述代码可能等同于:
const currentCount = this.state.count;
this.setState({count: currentCount + 1});
this.setState({count: currentCount + 1});
this.setState({count: currentCount + 1});
那么,如果我们需要最后的结果一定为3,我们可以怎么做?
通常做法是将this.setState()
的第一个参数修改为一个函数,该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数:
this.setState((prevState, props) => ({
counter: prevState.currentCount + 1;
}));
... // 重复调用3次即可
状态更新合并
state的更新是一个浅合并的过程,所以在更新state时,只需传入发生改变的state数据,而不用传入全都的state数据。
比如,你的组件的state包含多个变量:
constructor(props) {
super(props);
this.state = {
title: 'hello world',
name: '张三'
};
}
当你更新state中的name
属性时,只需要:
this.setState({name: '李四'});
React会合并新的name
到原来的state中,同时保留原有的状态title
,合并后的state结果为:
{
title: 'hello world',
name: '李四'
}
状态更新与Immutable
React官方建议把state中的数据当作是不可变对象,也就是说,当你想执行this.setState()
的时候,你应该做的是:重新创建一个新值来赋给state中的数据。
下面针对不同的数据类型分别描述。
数字,字符串,布尔值,null, undefined
针对基础类似数据的更新,直接赋值更新即可。
this.setState({
age: 20,
name: '李四',
success: true,
addr: null,
tags: undefined
});
对象
当state的数据为数组时,需直接赋值一个新的数组。若需要在袁数组上操作,可使用以下方法:
var arr = this.state.arr;
// 方法一
this.setState({ arr: [].concat(arr, ['arr1']) });
// 方法二
this.setState({ arr: [...arr, 'arr1'] });
// 方法三
this.setState({ arr: arr.slice(1, 3); });
// 方法四
this.setState({ arr: arr.splice(1, 3, 'arr1'); });
当state的数据为狭义上的对象时,可使用以下方法来修改原有对象:
var obj = this.state.obj;
// 方法一
this.setState({ obj: Object.assign({}, obj, {title: 'HELLO'}); });
// 方法二
this.setState({ obj: {...obj, title: 'HELLO'} });
状态更新与页面渲染
当新状态不同于之前状态时会触发重新渲染。所以,this.setState()
总是会触发页面的重新渲染。this.setState()
调用后,会触发生命周期的钩子函数shouldComponentUpdate
,若该函数返回值为false
,则不会触发重新渲染。
参考链接
- State & 生命周期,by React 中文网
- 深入理解State和setState()
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!