React18 setState异步更新

React18引入了自动批处理机制,优化了异步回调中的更新,减少了渲染次数。本文通过实例分析了setState的批处理更新,解释了在不同场景下如何依赖上一次的状态值进行异步更新,以及useState的闭包特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在v18之前,只有事件回调、生命周期回调中的更新会批处理,比如onClick。而在promise、setTimeout等异步回调中不会批处理,这就会导致多次render。React18实现了自动批处理,减少了更新次数,提升性能。

        接下来,简单分析下setState例子,加深对批处理更新的理解。

const [myState,setMyState] = useState(1);
const [flag, setFlag] =useState(true);

console.log('render');

const handleClick = ()=>{
        setMyState((myState) =>myState+6);
        console.log('myState1',myState);
        setMyState(myState+1); 
        setMyState((myState) =>myState+6);
        console.log('myState2',myState);
        setFlag((flag)=>!flag);
        setTimeout(()=>{
            setMyState(myState+1);
            console.log('myState3',myState);
            setMyState((myState) =>myState+10);
            console.log('myState4',myState);
        },1000)
}

return (
     <p>
         <button onClick={handleClick}>myState:{myState},flag:{flag?'true':'false'}</button>
     </p>   
    )

点击按钮之后将输出:

render

myState1 1
myState2 1
render
myState3 1
myState4 1
render

按钮上显示变化myState:1,flag:true 到 myState:8,flag:false, 到 myState12,flag:false

setState是异步更新的,setState((pre)=>...)此种更新方式将会依赖上一次的状态值,多个state更新会进行批处理更新,减少渲染次数。

点击按钮之后,setState将会在队列中排队,先抛开setTimeout里面的setState,此时为

setMyState((myState) =>myState+6);
setMyState(myState+1); 
setMyState((myState) =>myState+6);
setFlag((flag)=>!flag);

状态myState输出会先同步执行完,因为点击按钮时,当前状态中的myState为1,flag为true。所以输出两个myState3

队列中的setState,他们的上下文,作用域中myState为1,flag为true。

setMyState((myState) =>myState+6);  执行该更新会依赖上一个状态,上个状态为1,所以执行完后myState为7。

setMyState(myState+1);  这段很容易误解是7+1=8,其实不是。因为setState是异步的,当前队列里,它在寻找myState的值的时候,通过作用域找到的是状态的初始值1,所以该更新执行后myState变为2,即从7->2。

setMyState((myState) =>myState+6);执行这个状态更新的时候,它依赖上一个更新值,即2,所以这里的myState初始值为2,即从2->8。

最后是flag变为false。

此时按钮上显示的是myState:8,flag:false。

接着看setTimeout里的函数。同样的对列里是

setMyState(myState+1);
setMyState((myState) =>myState+10);

这里要注意,setTimeout整个函数式先执行的,回调会被放在宏任务里,它们的state的作用域是在click时候的状态下的上下文,即myState是1,flag是true。

setMyState(myState+1);,从1->2

setMyState((myState) =>myState+10); 从2->12。

按钮上显示myState12,flag:false。

在state变化过程当中,页面不会变化一次刷新一次,react框架层面会帮我们做批量更新。

有一点要注意:useState会形成闭包,setState是依赖执行更新状态时的值,而不是更新状态中的值(除setState(()=>{...}形式))。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值