---------------------------------------------------------------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博客

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐