React setState两种回调写法差异及回调获取旧状态问题
两种
setState写法差异及回调获取旧状态原因 两种写法的核心区别
- 第一种写法:直接将
callback作为setState的第二个参数传入,是React类组件setState(updater, [callback])的标准传参方式,正常逻辑下该回调会在状态合并完成、组件完成重渲染后被React调用。 - 第二种写法:传入的第二个参数是一个新的箭头函数,函数体内仅写了
callback没有加括号执行,属于无效写法——就算外层箭头函数被触发,内部的callback也不会实际运行。如果是笔误漏写了调用括号,实际代码是() => callback(),那这种写法只是多了一层箭头函数包裹,核心作用是固定this指向,和直接传callback的执行时机没有区别。
回调获取旧状态的核心原因
回调打印旧状态值,基本都是以下两类问题导致的:
- 回调函数的
this指向错误
如果传入的callback是类组件中未绑定this的普通方法,比如直接写setState(updater, this.handleLog),而handleLog是类中定义的普通方法,回调执行时this不会指向当前组件实例,此时读取的this.state要么是undefined,要么是其他作用域下的旧状态值。
这种场景下用箭头函数包裹一层(记得加括号执行回调,写成() => callback())就能解决问题,箭头函数会继承外层作用域的this,保证回调里拿到的是当前组件实例。 - 在函数组件中错误使用类组件API
带第二个回调参数的setState是React类组件的专属API,函数组件中useState返回的状态更新函数不支持第二个回调参数,就算传了回调,React也不会保证它在状态更新、重渲染完成后执行。此时回调里引用的state是定义回调时,当前渲染闭包捕获的旧状态值,自然打印的是更新前的结果。
函数组件要拿到更新后的状态,需要通过useEffect监听对应状态变化,在副作用函数中执行后续逻辑,不要给useState的更新函数传第二个参数。
代码中使用了
prevState => ({value: prevState.value +1})的函数式更新写法,已经避免了批处理导致的状态合并覆盖问题,基本可以排除状态更新本身失败的可能。
内容的提问来源于stack exchange,提问作者a2nineu
相关产品推荐
相关产品推荐

