当前位置: 首页 > 科技观察

小推理:React18比老版本的React好多了

时间:2023-03-16 21:19:49 科技观察

大家好,我是Kason。React18已经进入RC(releasecandidate)阶段,距离正式版仅一步之遥。V18增加了很多新特性。今天我们不说新特性,说说v18比老版本更好的一个细节:v18中,组件渲染的数量可能会少一些。国家从何而来?在以下组件中:functionApp(){const[num,update]=useState(0);//...useState会在App组件render省略后执行,返回最新的num值。换句话说,组件必须渲染才能知道最新状态。为什么会这样?考虑以下触发更新的代码:const[num,update]=useState(0);constonClick=()=>{更新(100);更新(数+1);update(num=>num*3);}onClick执行后,触发更新,更新导致App组件渲染,然后执行useState。在useState内部,num会按照以下过程计算:update(100)将num变为100update(num+1)将num变为100+1=101update(num=>num*3)将num变为101*3=303。即App组件渲染时,num为303。因此state的计算需要先收集触发的更新,然后在useState中统一计算。对于上面的例子,更新分别命名为u0~u2,那么state的计算公式为:baseState->u0->u1->u2=newState并发变化Concurrent(并发)给React带来“优先级”的概念是体现在“状态计算”上。根据触发更新的场景,更新有不同的优先级(例如onClick回调中触发的更新比useEffect回调中触发的更新具有更高的优先级)。计算状态所表达的差异是,如果更新具有低优先级,它将被跳过。假设上例中u1优先级低,当App组件渲染时,计算num状态的公式为://其中u1因为优先级低被跳过baseState->u0->u2=newState即就是:update(100)将num变成100。update(num=>num*3)把num变成100*3=300。显然这个结果是错误的。因此在并发情况下,React计算状态的逻辑会更加复杂。具体来说,它可能包含多轮计算。在计算状态时,如果跳过了一次更新,则下一次计算将从跳过的更新开始继续。例如,在上面的例子中,u1被跳过了。跳过u1时,num为100,此时的状态100,以及u1和“他之后的所有更新”都会被保存起来,参与下一次的计算。在示例中,它为u1和u2保存。下一次更新的情况如下:初始状态为100,update(num+1)将num变为100+1=101。update(num=>num*3)将num变为101*3=303。它可以看到最终结果303和“同步React”是一致的,但是需要渲染两次。“SynchronousReact”渲染一次,结果是303。“ConcurrentReact”渲染两次,结果是300(中间状态)和303(最终状态)。新旧Concurrent的区别从上面的例子我们发现,组件渲染的次数受“跳过了多少更新”的影响。事实上,它可能不仅渲染两次,而是多次。在旧版本的“ConcurrentReact”中,“优先级”是一个名为expirationTime的时间戳。比较“是否应该跳过更新”的算法如下://更新优先级是否低于渲染优先级if(updateExpirationTime