从现在开始赶上React18(上篇)
首先
虽然我想学习React18,但时间已经过去了一段日子。
然而,在此期间,肯定有些人已经追赶上了React18的变化和更新内容,而对于知道和不知道这些内容的人之间可能存在很大差距。本文的目标是让我这个追慢了步伐的人尽量赶上进度。
关于学习的必要性
由于React定期更新,因此很容易认为这次更新只是其中一部分。但实际上,这次更新被称为革命,有许多重大变化,预感到未来的前端开发将发生翻天覆地的变化。还有许多即将推出的功能正在准备阶段,所以这次更新是必看的。
概述
我认为,React18有许多更新,但只要掌握以下三个方面,就基本不会出错。
本文将讨论1和2两个方面。
-
- 自动分批
-
- 过渡
- 悬念
我想要一一地将各个功能和概要解析并输出。
关于「根」一词
在React18和之前的版本中,有一个重要的前提是在index.js中,ReactDOM的渲染方式有所不同,使用了createRoot进行渲染。
// React18 createRootにすると18の機能が使えるようになる
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
//React17
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementByID("root")
);
自动批处理
首先,我想先从自动批处理开始解释,但在此之前,我们将详细了解批处理。
“什么是批处理?
官方文档中对批处理的定义如下。”
批处理是指React将多个状态更新分组以提高性能,并在单个重新渲染中一起处理的过程。(引自React官方文档)
但是仅凭这样说可能不容易理解… 总的来说,即使在处理函数中调用了set函数等,也不需要每次都进行渲染,而是会自动地进行一定程度的整理和组合。
「我想吃一份炒面和一杯绿茶」
const [state1, setState1] = useState(false);
const [state2, setState2] = useState("");
const [state3, setState3] = useState(0);
-----------------中略--------------------
const onClickHandler = () => {
//set関数が3回も呼ばれているがその都度レンダリングが走るわけではなく、まとめて一回のみ走るようにしてくれる(バッチング)
setState1(true);
setState2("OK");
setState3(1000);
};
实际上,在React18之前,这种自动批处理已经存在,但在18版中发生的变化是除了事件处理程序之外,还开始进行批处理。
以前,除了事件处理程序外,其他都没有批处理。
在自动批处理之前,React只对事件处理器中的更新进行了批处理。Promise、setTimeout、本地事件处理器以及其他所有事件中发生的更新默认情况下都没有进行批处理。(来自官方文档)
有什么好处?
由于过去可能存在多次运行处理以及代码效率较低的情况,但在此次修订后,性能得到了提高。
顺便提一句,关于这次更新,我们这一边无需设置即会自动优化,但还是好好知道一下比较好。
关于过渡
关于过渡的问题
由于这次更新的内容发生了重大变化,所以需要特别关注的是这个 Transition。
在解释Transition之前,我想先看一下Transition解决了哪些问题。
在过去的开发(在引入Transition之前)
过去,没有优先级顺序进行更新。这就导致了以下问题的出现。
-
- 押したかどうか不安になるようなボタン
-
- 感度の悪い、絞り込みのためのタグ
- 数秒経った後に変化のある要素、などなど…
这些UX的不良例子都有一个共同点,那就是当用户进行某种行动(例如点击、聚焦等)时,响应速度会很慢。
以上所提到的例子,问题的原因是在进行繁重处理的同时还进行了渲染处理。
这个形象是这样的吧?
回应:「由于处理激烈的情感而感到疲倦,无法应对用户的行动?」
回应:「终于处理完了,可以应对行动了」← 这就是用户体验不好的原因
无论是哪个处理,以前的React都将其视为相同,也就是说无法给它们设置优先级。
因此,我们无法采取“先处理这个任务,因为它比较繁重,然后再处理那个任务”的做法。
不过,这样做不仅对用户体验不好,还会导致用户流失率增加的原因。
对于想要进一步了解以上内容的人来说,我推荐访问这个GitHub页面。
解决方案 cè)
为了解决这个问题,引入了一个新的功能,即前面提到的Transition概念。
Transition是什么?
转换(transition; 逐步推移)是React中的一个新概念,用于区分紧急更新和非紧急更新。
我认为,通过新的概念和功能产生的Transition是对用户体验有益的功能,未来这种功能会被普遍用于开发中。
用一句话概括是什么意思?
以往都是均等地更新,现在可以根据优先级进行更新了!
由于这一点,我们可以向React传达顺序,从而对其进行更新。
作为一个形象,应该是这样的感觉吧。
由于React「激活和用户操作」两个方面要处理,但被要求先更新用户操作,所以我们先从这边开始处理。
好的,立即采取行动,专注于激烈的处理。
实际代码的写法
import { useTransition } from 'react';
// ...
function ClassicAssociationsBubbles({associations}) {
// New hook in React 18
const [isPending, startTransition] = useTransition();
const [minScore, setMinScore] = useState(0.1);
const data = computeData(minScore);
return (
<>
<FastSlider defaultValue={0.1} onChange={val => {
// Update the results, in a transition.
startTransition(() => {
setMinScore(val);
});
}/>
<ExpensiveChart
// Use the isPending flag to add a pending class.
className={isPending ? 'pending' : 'done'}
data={data}
/>
</>
);
}
//このコードはReal world example: adding startTransition for slow renders #65から引用させていただきました。
可以使用useTransition来编写类似于上述代码的功能,并且被startTransition包裹的设置函数等将具有较低的优先级并被处理。
如果你想更加详细地了解,并且能够实际体验的话,我推荐参考以下相关文章✨
结束
我个人觉得 React18 这次更新可能会彻底改变未来的开发体验,因此我感到了一种预感,所以我希望能紧跟潮流,努力赶上!
请提供参考资料。