useTransition
用于 管理狀態更新的過渡(pending)狀態
,避免因高優先級任務(如用戶輸入)被低優先級任務(如數據獲取或復雜計算)阻塞而導致的界面卡頓。
它特別適用于,需要 區分緊急更新和非緊急更新 的場景。
useTransition 的核心作用
-
標記非緊急更新:
1、允許某些狀態更新(如:數據獲取、復雜計算)被標記為“過渡”(startTransition),讓 React 知道這些更新可以延遲執行。
2、緊急更新(如用戶輸入、動畫)會優先執行,避免界面卡頓。 -
顯示加載狀態:
在過渡期間,可以顯示一個加載指示器(如骨架屏、旋轉圖標),提升用戶體驗。 -
避免不必要的渲染:
如果過渡更新被更高優先級的更新打斷,React 會丟棄未完成的過渡更新,避免浪費資源。
基本用法
import { useState, useTransition } from 'react'function App() {const [ isPending, startTransition ] = useTransition()const [ list, setList ] = useState([])const [ inputValue, setInputValue ] = useState('')const handleInputChange = (e) => {setInputValue(e.target.value) // 緊急更新(用戶輸入)}const handleSearch = () => {startTransition(() => {// 模擬一個耗時的數據獲取操作const newList = fetchData(inputValue) // 非緊急更新(數據獲取)setList(newList)})}return (<div><inputtype="text"value={inputValue}onChange={handleInputChange}/><button onClick={handleSearch}>Search</button>{isPending && <p>Loading...</p>} {/* 顯示加載狀態 */}<ul>{list.map((item) => (<li key={item.id}>{item.name}</li>))}</ul></div>) // end-return
}// 模擬數據獲取
function fetchData(query) {// 假設這是一個耗時操作(如 API 請求)return Array.from({ length: 1000 }, (_, i) => ({id: i,name: `${query} Item ${i}`,}))
}
- 解析
-
useTransition
返回一個數組:
isPending
:布爾值,表示是否有未完成的過渡更新。
startTransition
:函數,用于標記某個狀態更新為“過渡”。 -
緊急更新 vs. 過渡更新:
緊急更新
(如 setInputValue)會立即執行,不會被延遲。
過渡更新
(如 setList)會被標記為低優先級,React 會在空閑時執行。 -
isPending 的作用
:
在過渡期間,isPending 為 true,可以用于顯示加載狀態(如 Loading…)。 -
startTransition 的使用
:
將耗時操作包裹在startTransition
中,告訴 React 這是非緊急更新。
總之
useTransition
是 React 18 提供的優化工具,用于 區分緊急和非緊急更新,避免界面卡頓。isPending
可以用于顯示加載狀態,提升用戶體驗。startTransition
用于標記非緊急更新,讓 React 知道可以延遲執行。
如果你的應用中有 耗時操作(如:數據獲取、復雜計算),并且希望 避免阻塞用戶交互,useTransition
是一個非常好的選擇! 🚀
useDeferredValue
useDeferredValue
的核心作用
-
延遲低優先級更新:
- 當某個狀態(如:輸入框的值)變化時,React 會優先處理高優先級任務(如:用戶輸入),而延遲處理低優先級任務(如:列表渲染)。
- 避免因列表渲染導致輸入框卡頓。
-
自動管理優先級:
- 不需要手動調用
startTransition
,useDeferredValue
會自動決定何時延遲更新。
- 不需要手動調用
-
避免不必要的渲染:
- 如果輸入值快速變化(如:用戶連續輸入),React 會丟棄未完成的低優先級更新,避免浪費資源。
基本用法
import { useState, useDeferredValue } from 'react'function SearchResults() {const [ query, setQuery ] = useState('')const deferredQuery = useDeferredValue(query) // 延遲更新后的值const [ list, setList ] = useState([])// 模擬數據獲取(耗時操作)const fetchData = (q) => {return Array.from({ length: 1000 }, (_, i) => ({id: i,name: `${q} Item ${i}`,}))}// 當 deferredQuery 變化時,更新列表// (但不會阻塞用戶輸入)React.useEffect(() => {setList(fetchData(deferredQuery))}, [deferredQuery])return (<div><inputtype="text"value={query}onChange={(e) => setQuery(e.target.value)}placeholder="Search..."/><ul>{list.map((item) => (<li key={item.id}>{item.name}</li>))}</ul></div>) // end-return
}
-
useDeferredValue
返回一個延遲的值:deferredQuery
是query
的延遲版本,React 會在空閑時更新它。- 用戶輸入(
query
變化)是緊急更新,會立即響應。 - 列表渲染(基于
deferredQuery
)是低優先級更新,會延遲執行。
-
自動優化性能:
- 如果用戶快速輸入,React 會丟棄未完成的
deferredQuery
更新,避免浪費資源。 - 只有當用戶停止輸入或輸入速度變慢時,才會執行低優先級更新。
- 如果用戶快速輸入,React 會丟棄未完成的
-
適用場景:
- 搜索框 + 動態列表:用戶輸入時,列表渲染不會阻塞輸入。
- 過濾/排序大數據:用戶調整篩選條件時,列表更新不會卡頓。
優化后的代碼示例(帶加載狀態)
import { useState, useDeferredValue, useEffect } from 'react'function SearchResults() {const [ query, setQuery ] = useState('')const deferredQuery = useDeferredValue(query)const [ list, setList ] = useState([])const [ isLoading, setIsLoading ] = useState(false)useEffect(() => {setIsLoading(true)const timer = setTimeout(() => {setList(Array.from({ length: 1000 }, (_, i) => ({id: i,name: `${deferredQuery} Item ${i}`,})))setIsLoading(false)}, 300)return () => clearTimeout(timer) // 清理未完成的更新}, [deferredQuery])return (<div><inputtype="text"value={query}onChange={(e) => setQuery(e.target.value)} />{isLoading && <p>Loading...</p>}<ul>{list.map((item) => (<li key={item.id}>{item.name}</li>))}</ul></div>) // end-return
}
總結
useDeferredValue
是 React 18 提供的優化工具,用于 延遲低優先級狀態更新,避免阻塞用戶交互。- 適用場景:輸入框關聯的動態內容(如搜索建議、過濾列表)。
- 優勢:
- 自動管理優先級,無需手動調用
startTransition
。 - 避免因低優先級任務導致界面卡頓。
- 提升用戶體驗,特別是在輸入場景下。
- 自動管理優先級,無需手動調用
如果你的應用中有 輸入框 + 動態列表 的交互,useDeferredValue
是一個非常合適的優化方案! 🚀