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

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

React之this.setState使用需知注意点 -this.setState无法正确改变state值最近在项目中,出现了一些用setState()无法给state中的变量正确赋值的情况,特此总结一下this.setState使用的注意点。那为什么用this.setState()会出现一些跟我们常规逻辑不相符的地方呢?请看下表(两个特性即为两个需要注意的点):(思路: 因为它这样的特...
react中通过 state 以及 setState() 来控制组件的状态。 state statereact 中用来存储组件数据状态的,可以类比成 vue 中的 data。 1.state的作用 stateReact中组件的一个对象.React把用户界面当做是状态机,想象它有不同的状态然后渲染这些状态,可以轻松让用户界面与数据保持一致. React中,更新组件的state,会导致重新渲染用户界面(不要操作DOM).简单来说,就是用户界面会随着state变化而变化. 2.state工作原理 常用的通知React数据变化的方法是调用setState(data,callback).这个方
日志打印的还是未初始化的数据 this.setState()是异步方法,也就是说,setState还没有执行完成,日志打印方法已经触发了,导致以为没有正确初始化。 需要在回调中调用打
1.击按钮,实现index++的情况,很多同学在用this.setState({})的方法如下: <ButtononClick={this.onChange}>addField</Button> onChange=()=>{ const { index } = this.state; this.setState({ index:index++ }); // 其实这种方法不能实现index++的效果.这是异步的处理方法不能实现同步this.s...
根据上图可以看出当我添加了一个新的任务,并且用setState修改state,数据依旧没有发生变化,但是在第二次添加的时候发生了变化,总是比我添加的总数慢一个数,这个时候我就在考虑是不是因为异步问题 经过查询:setState本身并不是异步,只是因为React的性能优化机制体现为异步。在react的生命周期函数或者作用域下为异步,在原生的环境下为同步。 .........
1.为什么不要直接对state进行赋值? 如果直接对this.state复制是不会去更新视图的,this.setState的原理是同一个队列来实现state的更新的,将需要更新的state放入到状态队列中,在一定时间段之后,合并并更新state,然后进行渲染.而直接对this.state赋值是不会有这些操作的,因此不要对state进行直接赋值. 2.this.setState为什么是异步的? this.setState的操作是异步的,是为了提升性能对state的更新进行批量操作,官方文档中的原话:
import React, { Component } from "react"; import "./scss/header.scss"; export default class header extends Component { state = { header: "", setStateAsync = (state) => { return new Promise((resolve, reject) => { this.setState(s
今天同事在开发过程中遇到了个问题,在使用AntD的Form组件时,内置的onFinish方法里面调用了2次setState方法,发现return函数渲染了2次,不过我记得多次调用setState时,会批量合并,所以就产生了一些疑惑,就上网查了一些资料,学习记录一下。 1、setState使用 使用React的应该都知道,在React中,一个组件中要读取当前状态需要访问this.state,但是更新状态却需要使用this.setState,不是直接在this.state上修改。 setState(u