useDeferredValue
useDeferredValue
的实际功能可能跟它的字面意思不是很一样,它提供的并不是一种 State,而是用来延迟 UI 的更新的。在组件中使用useDeferredValue
可以获取指定值的延迟版本,通常与useState
组合使用。useDeferredvalue
打的返回值在组件初始渲染时与原始值相同,但是在组件更新的时候,React 会首先尝试使用旧值做组件的重新渲染,然后在后台使用新值做另一个重新渲染。
React 在后台会使用Object.is
来比较旧值和新值,如果两者不同,那么 React 将会安排一个后台渲染,但这个后台渲染是可以被中断的。如果在 React 进行后台渲染期间,useDeferredValue
接收到了另一个新值,那么之前的后台渲染就将会被中断。这个操作十分类似于常见的数据防抖操作,但是useDeferredValue
的防抖时间阈值非常的小,所以不要将其做作为防抖方法使用。
useDeferredValue
的主要功能还是用来在新内容加载期间展示用于替代的旧内容,改善 UI 的显示效果。需要注意的是,useDeferredValue
的后台渲染不会触发任何useEffect
定义的副作用,所有的副作用会在 UI 更新后执行。
useDeferredValue
最典型的使用案例就是延迟更新数据列表,例如以下示例。
function DeferredList() {
const [quest, setQuery] = useState([]);
const deferredQuery = useDeferredValue(query);
return (
<>
<div>
<label>Search Keyword: </label>
<input value={query} onChange={(e) => setQuery(e.target.value)} />
</div>
<Suspense fallback={<span>Loading...</span>}>
<SearchResults query={deferredQuery} />
</Suspense>
</>
);
}
以上示例将useDeferredValue
与<Suspense>
组件搭配使用了,这可以达到在<SearchResults>
组件未完成数据加载的时候,先展示旧数据和加载提示的效果。
如果需要判断当前展示的数据是新值还是旧值,在以上示例中可以使用query !== deferredQuery
来判断。如果它们两个不相等,那么当前展示的就依旧是旧值,否则就是新值了。