React之this.setState使用需知注意点 -this.setState无法正确改变state值

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为什么不同步更新

(当然因为它不是异步的,只是一些情况下同步更新,一些情况下不同步更新)

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值