useState 讲解 如何改成同步方法
在useState()第一次存储的时候,值会存储不上因为react中state的更新是异步的,我们setState后,react不会立刻对值进行改变,而是将其暂时放入pedding队列中。useState()初始值最好是useState({statefalse,xxxx}),采用{}增加可扩展性。再次更新,useState是同步方法,只是react的流程调度把useState变成了异步方法的样子。
---------------------------------------------------------------2023 12 28 ------------------------------------------------
useState是同步还是异步方法,如何触发同步更新?
在react17及以前的版本,原生事件里调用setState会触发同步更新 。
在react18版本,即使在原生事件里调用setState也不会触发同步更新 。
为什么,咱们要从react的启动模式说起。
react启动模式有三种,通常使用第一种和第三种: legacy 模式 ,blocking 模式 , concurrent 模式 .
在react 17 版本默认的启动模式是 legacy 模式 , 但react18模式后 默认的启动模式是 concurrent 模式 。 这次更新是一次底层的 reconciler 渲染调度的革命性更新 。
它让react 可以在触发setState同步渲染的过程,如果有高优先级的任务(例如用户的点击事件)进来,它会优先处理。
之前react17的版本legacy 模式,它构建dom的过程是同步的,所以在render的reconciler中,如果diff的过程特别耗时,那么导致的结果就是js一直阻塞高优先级的任务(例如用户的点击事件),表现为页面的卡顿,无法响应。
参考:react源码解析6.legacy模式和concurrent模式 - 知乎
在react里在发原生事件里setState有两种方法就是:
1、 window.addEventListener('scroll', ()=>{})
2、 <Button onClock = {(e) => {e . nativeEvent. xxx }} > (我没这样用过,纯属没用,只是看网上文章有这样写,顺便记录一下 , 真正在原生事件种调用setState的一般只会用第一种方法)
---------------------------------------------------------------2023 12 28 ------------------------------------------------
把useState改成同步方法
1. 用 useEffect 中监听 state变化 ( 不行 )
当useEffect 监听到 state 变化时,再去执行下一步操作 。 相当于,state 已经改变了再去执行自己的逻辑。 但这样写, 真的垃圾 ,不实用。
2. 用 回调函数传参 方法获取最新的值,同时用 promise 变成同步方法 。 (麻烦)
例子:
const [count1, setCount1] = React.useState(0);
const [count2, setCount2] = React.useState(0);
new Promise((resolve) => {
setCount((num) => {
resolve(num + 1); // 也可以传空值过去
return num + 1;
});
}).then(res => {
seyCount2(res);
});
3.( 我自己总结的 ) 在setState( value )的同时, 把 value 赋一份给 useRef 。
例子:
[ Count,setCount ] = useState(0)
a = useRef()
fn ( ) {
setCount ( Count + 10 )
a.current = Count + 10
后面的业务逻辑,都用 a.current 去操作。 之所以要 setCount,是为了让函数刷新,同时更新Count的值。
}
---------------------------------------------------------------------------------------------------------
setState( ) 可以接受一个回调函数,里面的参数State是 最新的State 。
例子:
[ Count,setCount ] = useState(0)
setState(( preState )=> { preState + 1 } ) //这里的preState 是 0
setState(( preState )=> { preState + 2 } ) //这里的preState 是 1
结果 state 是 3
例子: 普通形式:
setState(preState + 1 ) //这里的preState 是 0
setState(preState + 2 ) //这里的preState 是 0
结果 state 是 2
------------------------------------------------------------------------------------------------------------------------
useState() 初始值最好是 useState({ state:false,xxxx }),采用{ }增加可扩展性
setXXX的时候, 可以这样 setXXX({....XXX,state:true})
或者 setXXX(object.assign({ },XXX,{state:true}))

---------------------------------------
再次更新, useState 是同步方法, 只是react的流程调度把useState变成了异步方法的样子。
react的流程调度里,会把多个事件合成一个事件,一次性处理,所以,变成了异步
---------------------------------
useState() 属于异步函数
,在useState() 第一次存储的时候,值会存储不上 因为react中state的更新是异步的,我们setState后,react不会立刻对值进行改变,而是将其暂时放入pedding队列中。react会合并多个state,...
合并更新造成的数据不能及时更新(非标准异步过程)
useState 返回的更新状态方法是异步的,要在下次重绘才能获取新值。不要试图在更改状态之后立马获取状态。
-----------------------------------------------------------------------------------------------------------------------------
解决方法: 使用 useRef存值
网上: 还有个说,用异步回调,个人测试没用,同一个函数内,set完后,马上调用不能获取最新值。 评论:非常感谢🙏!这样写虽然,在函数内部仍然打印不到改变后的值,但是render上的值已经可以实时更新了。感谢。
react启动的模式
参考:react useState数据更新不同步问题_vin灵一的博客-CSDN博客_usestate如何同步更新
https://www.csdn.net/tags/MtTaEg5sMzcxMDczLWJsb2cO0O0O.html
hook useState实现class组件setState的callback?_moreInternet的博客-CSDN博客
更多推荐


所有评论(0)