当我们的程序中存在大量数据列表或者有一段时间密集型计算的时候,然后页面又需要监听状态改变的情况时,我们就可以使用useTransition
钩子函数来解决这个问题。例如如下的程序:
const [input, setInput] = useState<string>("");
const [list, setList] = useState<string[]>([]);
const LIST_SIZE = 20000;
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setInput(e.target.value);
const l = [];
for (let i = 0; i < LIST_SIZE; i++) {
l.push(e.target.value);
}
setList(l);
}
return (
<div>
<input type="text" value={input} onChange={handleChange} />
{list.map((item, index) => {
return <div key={index}>{item}</div>;
})}
</div>
);
运行上述代码后,我们会发现在输入框中输入字符后需要等待很长时间后,页面才会记性列表的渲染。当我们连续输入多个字符的时候,我们页面会出现卡顿的情况。
上述例子我们调用了setInput
或者调用了setList
后,React 会将状态更改的动作组合到一个调用中,即把setInput
和setList
合并成一个调用函数,然后等 for 循环完成后再重新一次性重新渲染我们的页面。
useTransition 钩子函数的作用就相当于对所有钩子函数排个优先级,然后程序运行时,首先把函数运行令牌给优先级高的钩子函数进行执行,等优先级高的钩子函数完成所有业务后,会把运行令牌传递给下一个优先级高的钩子函数执行依次类推,等所有钩子函数执行完成后,React 就会重新帮我们渲染页面元素。
我们就以上述案例为例进行修改。在上述的例子中,我们有setInput
和setList
两个钩子函数,从业务功能分析来看我们的setInput
是优先级比较高的,所以我们可以把它设置为优先级高的钩子函数,即用户一直在输入的时候,后台的程序一直在监听输入框的值改变,只有当用户不输入之后,系统才会调用setList
钩子函数。
具体的实例代码如下:
const [isPending, startTransition] = useTransition();
const [input, setInput] = useState<string>("");
const [list, setList] = useState<string[]>([]);
const LIST_SIZE = 20000;
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
setInput(e.target.value);
startTransition(() => {
const l = [];
for (let i = 0; i < LIST_SIZE; i++) {
l.push(e.target.value);
}
setList(l);
});
}
return (
<div>
<input type="text" value={input} onChange={handleChange} />
{isPending ? (
<p>数据加载中……</p>
) : (
list.map((item, index) => {
return <div key={index}>{item}</div>;
})
)}
</div>
);