useDeferredValue
useDeferredValue 是 React 18 引入的一个 Hook,用于延迟更新某些非关键渲染内容,以提升性能。它通过将低优先级的更新推迟到高优先级任务完成后执行,避免主线程阻塞,尤其适用于
输入框联想搜索
等场景。
核心功能
- 延迟渲染:接收一个状态值,返回一个延迟版本的值。React 会在高优先级更新完成后,再处理该值的更新。
- 优先级调度:与并发模式(Concurrent Mode)协同工作,确保用户交互(如输入)的流畅性。
基本用法
// query:实时响应用户输入的状态
// deferredQuery:延迟更新的值,传递给耗时的子组件(如搜索结果列表)
const deferredQuery = useDeferredValue(query);
适用场景
✅ 输入联想搜索:输入框内容实时更新,但搜索结果可稍后渲染。
✅ 大数据列表渲染:避免列表渲染阻塞用户交互。
✅ 非关键UI更新:如次要图表、统计数据的延迟加载。
useTransition 和 useDeferredValue 的区别
useTransition 是“我推迟我发起的更新”, useDeferredValue 是“我推迟别人传给我的值”
维度 | useTransition | useDeferredValue |
---|---|---|
控制对象 | 状态更新函数(setState) | 某个具体值(props / state) |
触发主体 | 当前组件主动发起更新 | 父组件传值,当前组件被动“延缓” |
返回值 | [isPending, startTransition] | deferredValue |
典型场景 | 路由切换、筛选项、搜索按钮点击 | 实时搜索输入框、高频变化的列表渲染 |
是否产生加载状态 | 有 isPending 布尔值 | 无内置加载状态,需自己对比 value !== deferredValue |
是否可取消/跳过 | 高优先级更新可中断低优先级 | 同左(都是 concurrent render) |
简单来说:
- 需要
点按钮
、选筛选项
、切路由
→ 用 useTransition - 需要
输入框实时反映
、列表慢点渲染
→ 用 useDeferredValue
小栗子-延迟搜索数据的更新
import React, { useState, useTransition, useDeferredValue } from 'react'
import { Input, List } from 'antd'
import mockjs from 'mockjs'
// 定义列表项数据类型
interface ResultType {
name: number // 名称
address: string // 地址
}
export function UseTransition() {
const [val, setVal] = useState('')
const [list] = useState<ResultType[]>(() => {
return mockjs.mock({
'list|10000': [
{
name: '@natural',
address: '@county(true)'
}
]
}).list
})
// val 时时状态, deferredQuery 延迟后的状态
const deferredQuery = useDeferredValue(val)
const isStale = deferredQuery !== val // 检查是否为延迟状态
const findItem = () => {
console.log(`${deferredQuery}---${val}`)
return list.filter(item => item.name.toString().includes(deferredQuery))
}
return (
<div>
<Input value={val} onChange={(e) => setVal(e.target.value)} />
<List loading={isStale} renderItem={(item) => <List.Item>
<List.Item.Meta title={item.name} description={item.address} />
</List.Item>} dataSource={findItem()}>
</List>
</div>
)
}
效果如下:
注意:
useDeferredValue 并不同于防抖机制,它并不能设置延时时间。useDeferredValue的延时时间是根据设备性能来的。