文章目录
前言
本文已收录在 Github: https://github.com/beichensky/Blog 中,欢迎 Star,欢迎 Follow!
在 React 18 新特性(一):自动批量更新 一文中提到:在 React 新版本中,更新会有优先级的顺序。
那如果希望更新时进行低优先级的处理,应该如何做呢,就是今天讲到的主题:渐变更新。
如果还不知道如何搭建 React18 的体验环境,可以先查看这篇文章:使用 Vite 尝鲜 React 18
一、startTransition:渐变更新
-
startTransition
接受一个回调函数,可以将放入其中的setState
更新推迟 -
允许组件将速度较慢的更新延迟渲染,以便能够立即渲染更重要的更新
举个例子
先来看一个例子,在使用谷歌或者百度搜索时,都会遇到如下的场景:
这里的展示分为两部分
-
一部分是输入框中的搜索内容
-
另一部分是展示的联想内容。
从用户的角度进行分析:
-
输入框中的内容是需要即时更新的
-
而联想出来的内容是需要进行请求或者加载的,甚至于最开始的时候联想的不准确,用不到。所以用户可以接受这部分内容有一定延迟。
那在这种情况下,用户的输入就是高优先级操作,而联想区域的变化就属于低优先级的操作。
模拟代码实现这个例子
我们写一段代码来实现一下这个搜索框。
App.jsx
import React, { useEffect, useState, startTransition } from 'react';
import ReactDOM from 'react-dom';
const App = () => {
const [value, setValue] = useState('');
const [keywords, setKeywords] = useState([]);
useEffect(() => {
const getList = () => {
const list = value
? Array.from({ length: 10000 }, (_, index) => ({
id: index,
keyword: `${value} -- ${index}`,
}))
: [];
return Promise.resolve(list);
};
getList().then(res => setKeywords(res));
}, [value]);
return (
<>
<input value={value} onChange={e => setValue(e.target.value)} />
<ul>
{keywords.map(({ id, keyword }) => (
<li key={id}>{keyword}</li>
))}
</ul>
</>
);
};
// 使用 react 18 新的并发模式写法进行 dom render
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
// legacy 旧模式
// ReactDOM.render(<App />, document.getElementById('root')!)
然后我们先看一下现在的效果(这里暂时不讨论防抖或者节流):
可以看到,不仅联想区域的内容加载缓慢,甚至用户的交互内容也反应迟钝。
既然刚才说到了低优先级更新,那么此时,我们是否可以让联想区域的内容低优更新,以避免抢占用户操作的更新呢?
接下来主角登场,使用 startTransition
对代码进行改造。
启用渐变更新
App.jsx
import React, { useEffect, useState, startTransition } from 'react';
import ReactDOM from 'react-dom';
const App = () => {
const [value, setValue] =