React之this.setState使用需知注意点 -this.setState无法正确改变state值
遇到this.setState无法正确改变这种情况,
很有可能是这样的:
通常情形
this.state = {
dataType: 'student',
};
onClick = () => {
this.setState({ dataType: 'teacher' });
fetchData(dataType);
};
1 你有一个state叫做 dataType, 默认值是 student;
2 在onClick的时候改变dataType(想要从 student 变为 teacher);
3 并且,想用改变后的dataType请求数据;
4 此时你发现:然而并没有,你希望的结果是fetchData(‘teacher’), 但实际是fetchData(‘student’);
所以就出现了this.setState无法正确改变state值的疑惑…
解决方法:
原因:
其实this.setState是正确的改变了state的值,只是由于this.setState的不同步,在你想使用改变后的state值时,它还没来得及更新
解决:
在this.setState()的第二个参数为回调函数,可获取到更新后的state值
对于刚才那个情形,解决方法如下代码:
this.state = {
dataType: 'student',
};
onClick = () => {
this.setState(
{ dataType: 'teacher' },
// 解决方法:
// 第二个参数:回调函数,用改变后的state值do something
() => {
fetchData(dataType); // fetchData('teacher');
});
};
正常来说,这样问题应该解决啦!
如果只想解决问题的话,这就是这篇文章的END啦。
如果你想对this.setState()的两个参数的具体使用情形进一步了解,请继续往下看~
重点说一说:
this.setState()不保证是同步的,那我们要怎么按需用它去改变state?
答案就是: 通过this.setState()的两个参数去控制
this.setState(param1, param2);
param1: 对象或函数 --- 改变state的值
param2: 回调函数 --- 等待state更新后,执行的函数
我们通过改变state中的showTable这个例子来看:
this.state = {
showTable: false,
};
1.要改变showTable的值,设置第一参数
用this.setState(对象):
// 第一个参数:对象
onClick = () => {
this.setState({ showTable: true });
console.log('showTable:', this.state.showTable);
};
onClick(); // 输出: showTable: false
注意this.setState()很多情况下都是不同步的。
所以,在你调用setState的地方,showTable的值并不会立马true。
console.log时,this.setState({ showTable: true })在执行队列中还未被执行。
用this.setState(函数):
// 第一个参数:函数,等待前面的更新完毕后传入最新的状态值
onClick = () => {
this.setState((prevState, props) => ({ showTable: true })); // 用函数代替对象
console.log('showTable:', this.state.showTable);
};
onClick(); // 输出: showTable: false
console.log的值还是false!!!因为用函数代替对象,给state赋值,并不会改变它执行的顺序,改变的是:
showTable会等待之前的state更新完毕之后,传入最新的state值
那这样的话,用函数作第一参数的价值在哪里?
就是它可以用在:此次state的改变,需要依赖上一次改变的值
比如以下代码:控制showTable在true和false之间来回切换,如果上一次是true,则变为false,如果上一次是false,这一次是true
// 第一个参数:函数,等待前面的更新完毕后传入最新的状态值
onClick = () => {
this.setState((prevState, props) => ({ showTable: !prevState }));
};
2. 要等showTable的值更新后做一些事,用第二个参数
this.setState()的第二个参数是回调函数,在等第一个参数内的state更新后调用
// 第二个参数:回调函数,在等待第一个参数更新之后调用
onClick = () => {
this.setState(
// 第一个参数: 改变state
{ showTable: true },
// 第二个参数:回调函数,用改变后的state值do something
() => {
// do something here...
console.log('showTable in callback', this.state.showTable);
});
console.log('showTable:', this.state.showTable);
};
onClick();
// 输出:
// showTable: false;
// showTable in callback: true;
注意log打印的顺序!是‘showTable’先打印的,等到state值改变之后,才打印了‘showTable in callback’
更说明了this.setState()不同步更新的问题
总结一下,
- 正常情况下,this.setState(对象)去改变state的值
- 如果state的值需要依赖之前的state更新,就用this.setState(函数)去改变state的值
- 如果你要用更新后的state值去做一些事,就写在this.setState({}, callback)的回调函数中
附上this.setState()的两个特性:
特性 | 后果 | 解决 |
---|---|---|
this.setState()不保证是同步的 | 无法正确改变state的属性值,或者无法按我们的设想去改变state | 利用this.setState()的第一参数,第二参数来解决 |
this.setState()将总是触发一次重绘 | 会造成不必要的渲染 | 1 生命钩子函数componentShouldUpdate()中优化; 2 与渲染无关的变量不要存在state中 |
到这里,this.setState()的正确使用应该是基本掌握了
如果觉得有用,请给我点赞或评论提问提修改意见哦~
如果你还对一个问题有兴趣 or 有疑问:
为什么各种文章里都是说this.setState()不同步,而不是直接说this.setState()异步呢
or
为什么各种文章里都是说this.setState()不同步,那它有同步的时候吗
这也是我曾有过的迷惑啊,请看这篇文章讲得很清楚:
this.setState为什么不同步更新
(当然因为它不是异步的,只是一些情况下同步更新,一些情况下不同步更新)