1. Automatic batching
以往在事件中setState,react会将多个set操作合并成一次,例如: sandbox
function handleClick() {
console.log("=== click ===");
setCount((c) => c + 1);
setFlag((f) => !f);
}
// // 两次set会被合并处理
但是在异步操作中比如:setTimeout 或 fetch,set操作并不会合并。sandbox
function handleClick() {
console.log("=== click ===");
fetchSomething().then(() => {
// React 17 and earlier does NOT batch these:
setCount((c) => c + 1); // Causes a re-render
setFlag((f) => !f); // Causes a re-render
});
}
所以有些第三方库会手动合并:
import { unstable_batchedUpdates } from 'react-dom';
unstable_batchedUpdates(() => {
setCount(c => c + 1);
setFlag(f => !f);
});
// 两次set会被合并处理
React18 将提供自动批处理功能,只要使用ReactDOM.createRoot,代替ReactDOM.render。
若部分需求不想使用批处理,可以使用flushSync:
import { flushSync } from 'react-dom'; // Note: react-dom, not react
function handleClick() {
flushSync(() => {
setCounter(c => c + 1);
});
// React has updated the DOM by now
flushSync(() => {
setFlag(f => !f);
});
// React has updated the DOM by now
}
2. Behavioral changes to Suspense in React 18
React官方将18版本的Suspense称作"Concurrent Suspense",16、17版本的Suspense称作"Legacy Suspense"。
以下面代码为例:
<Suspense fallback={<Loading />}>
<ComponentThatSuspends />
<Sibling />
</Suspense>
区别在于被挂起的组件的兄弟节点。
在Legacy Suspense中 ,Sibling 会立即挂载到DOM中,并触发生命周期。sandbox
在Concurrent Suspense,其兄弟节点Sibling 组件没有立即挂载到 DOM。它的effect/生命周期也不会在 ComponentThatSuspends 解决之前触发。sandbox
其目的是延迟子树的渲染,直到树中的所有数据都已解析。
3.New feature: startTransition
属于一个性能优化的API,以下结论参考:Real world example: adding startTransition for slow renders
解决什么问题
目前我把它理解为:更聪明的防抖截流,方便理解
官方提供了一个很具体例子(例子具体的好处是方便理解startTransition的作用,但也有坏处,就是除此之外我在想不到他的用处):
做可视化时可能遇到,有一个滑块,可以调节阈值,滑块下边是一个关系图。
滑动滑块,阈值变化引起数据变化,数据变化引起关系图变化
好的实现:2021-06-22.at.9.42.18.AM.mov
一般实现:2021-06-21.at.3.43.50.PM.mov
无任何优化的实现:2021-06-21.at.1.16.51.PM.mov
如何解决的
Updates wrapped in startTransition are handled as non-urgent and will be interrupted if more urgent updates like clicks or key presses come in. If a transition gets interrupted by the user (for example, by typing multiple characters in a row), React will throw out the stale rendering work that wasn’t finished and render only the latest update.
包含在 startTransition 中的更新被视为非紧急更新,如果出现更紧急的更新(如点击或按键),则会被中断,如果transition被用户打断(例如,通过在一行中输入多个字符),React 将丢弃未完成的陈旧渲染工作并仅渲染最新更新。
Yielding: every 5 ms, React will stop working to allow the browser to do other work, like run promises or fire events.
让渡:每 5 毫秒,React 将停止工作以允许浏览器执行其他工作,例如运行promise或触发事件。
Interrupting&Skipping old results:: If a transition gets interrupted by the user (for example, by typing multiple characters in a row), React will throw out the stale rendering work that wasn’t finished and render only the latest update.
- 打断&舍弃旧结果:如果transition被用户打断(例如,通过在一行中输入多个字符),React 将丢弃未完成的陈旧渲染工作并仅渲染最新更新。
与setTimeout的不同
- setTimeout is Asynchronous but startTransition is synchronous.
We can see that startTransition doesn't change the order of events, it is still there but it will "wait" urgent events to finish then it will execute.
gif来自:知乎
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。