您好,登錄后才能下訂單哦!
這篇文章主要介紹“react18中的Transition怎么用”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“react18中的Transition怎么用”文章能幫助大家解決問(wèn)題。
React 18中,引入了一個(gè)新概念——transition
,由此帶來(lái)了一個(gè)新的API——startTransition
和兩個(gè)新的hooks——useTransition
和usedeferredValue
,本文由此展開(kāi)使用嘗鮮介紹。
1. 總覽
本文分為4部分進(jìn)行:
tansition
產(chǎn)生初衷
startTransition
使用和介紹
useTransition
使用和介紹
useDeferredValue
使用和介紹
2. transition產(chǎn)生初衷
transtion
直接翻譯為 過(guò)渡
。tansition本質(zhì)上是為了解決渲染并發(fā)問(wèn)題所提出
。在React中一旦組件狀態(tài)改變并觸發(fā)了重新渲染,則無(wú)法停止渲染。直到組件重新渲染完畢,頁(yè)面才能繼續(xù)響應(yīng)用戶(hù)的交互。
為此react 18中更新都可以劃分為以下兩類(lèi):
緊急更新
(urgent update):用戶(hù)期望馬上響應(yīng)的更新操作,例如鼠標(biāo)單擊或鍵盤(pán)輸入。
過(guò)渡更新
(transition update):一些延遲可以接受的更新操作,如查詢(xún)時(shí),搜索推薦、搜索結(jié)果的展示等。
// 被startTransiton標(biāo)記后為過(guò)渡更新 startTransition(()=> { // 非緊急更新,會(huì)被降低優(yōu)先級(jí),延遲執(zhí)行 setQueryValue(inputValue) }) // 未被標(biāo)記則馬上執(zhí)行 setInputValue(inputValue)
在react 18中被startTrionstion
標(biāo)記的更新,即為過(guò)渡更新(執(zhí)行的優(yōu)先級(jí)被降低),此時(shí)react會(huì)根據(jù)內(nèi)部的調(diào)度機(jī)制延遲執(zhí)行內(nèi)部的state更新。
開(kāi)發(fā)中開(kāi)發(fā)者可以通過(guò)transition hook決定哪些更新被標(biāo)記為transition事件。一旦被標(biāo)記則代表為低優(yōu)先級(jí)執(zhí)行,即react知道該state可以延遲更新,通過(guò)區(qū)分更新優(yōu)先級(jí)
,讓高優(yōu)先級(jí)的事件保持響應(yīng),提高用戶(hù)交互體驗(yàn),保持頁(yè)面響應(yīng)
。
3. startTransiton
startTransiton使用介紹
const handleClick = () => { // startTransition包裹標(biāo)記為低優(yōu)先級(jí)更新 startTransition(()=> { setQueryValue(inputValue) }) // 未被標(biāo)記則馬上執(zhí)行 setInputValue(inputValue) }
首先我們來(lái)介紹下最簡(jiǎn)單的startTransition
startTransiton 是一個(gè)接受回調(diào)的函數(shù),用于告知React需要延遲更新的state。
如果某個(gè)state的更新會(huì)導(dǎo)致組件掛起,則應(yīng)該包裹在startTransition中
通過(guò)演示對(duì)比
這是一個(gè)對(duì)輸入字符后展示搜索結(jié)果的場(chǎng)景模擬,通過(guò)偽造大量搜索結(jié)果,模擬容易卡頓的情況。
我們?cè)囍B續(xù)輸入123,監(jiān)聽(tīng)搜索框值value
變化(urgent update)和搜索值searchVal
變化(transition update)并輸出到控制欄。
import React, { useEffect, useState, startTransition } from 'react'; import './App.css' const SearchResult = (props) => { const resultList = props.query ? Array.from({ length: 10000 }, (_, index) => ({ id: index, keyword: `${props.query} -- 搜索結(jié)果${index}`, })) : []; return resultList.map(({ id, keyword }) => ( <li key={id}>{keyword}</li> )) } const App = () => { const [type, setTpye] = useState(1) const [value, setValue] = useState(''); const [searchVal, setSearchVal] = useState('-'); useEffect(() => { // 監(jiān)聽(tīng)搜索值改變 console.log('對(duì)搜索值更新的響應(yīng)++++++' + searchVal + '+++++++++++') }, [searchVal]) useEffect(() => { console.log('對(duì)輸入框值更新的響應(yīng)-----' + value + '-------------') if (type === 1) { setSearchVal(value || '-') } if (type === 2) { startTransition(() => { setSearchVal(value || '-') }) } }, [value, type]); return ( <div className='App'> <input value={value} onChange={e => setValue(e.target.value)} /> <div className={`type_button ${type === 1 ? 'type_button_checked' : ''}`} onClick={() => setTpye(1)}>normal</div> <div className={`type_button ${type === 2 ? 'type_button_checked' : ''}`} onClick={() => setTpye(2)}>transiton</div> <ul> <SearchResult query={searchVal}></SearchResult> </ul> </div> ); };
普通模式下
如圖所示:
連續(xù)輸入字符123,當(dāng)?shù)谝粋€(gè)字符輸入后,搜索值馬上響應(yīng),列表渲染立刻開(kāi)始,造成卡頓輸入框停止了對(duì)用戶(hù)輸入的響應(yīng),直到渲染結(jié)束,輸入框才繼續(xù)響應(yīng)。
使用startTransition后
如圖所示:
連續(xù)輸入字符123,輸入框不斷響應(yīng),搜索值的響應(yīng)被延后,保證頁(yè)面反饋,直到輸入結(jié)束,才開(kāi)始響應(yīng)搜索值,渲染搜索結(jié)果,保持頁(yè)面響應(yīng)。
4. useTransiton
useTransiton使用介紹
import { useTransiton } from 'react' const [isPending, startTransition] = useTransiton({timeoutMs: 2000}) // 例如, 在pending狀態(tài)下,您可以展示一個(gè)Spinner { isPending ? < Spinner /> : null }
startTransition
是一個(gè)接受回調(diào)的函數(shù),用于告知React需要延遲更新的state。
isPending
是一個(gè)布爾值,這是react告知我們是否等待過(guò)渡完成的方式。
useTransition
接受帶有 timeoutMs
的延遲響應(yīng)的值,如果給定的timeoutMs內(nèi)未完成,它將會(huì)強(qiáng)制執(zhí)行startTransition
回調(diào)函數(shù)內(nèi)state的更新。
useTransiton簡(jiǎn)單分析
我們通過(guò)偽代碼理解下useTransition
。
function useTransition(){ const [isPending, setPending] = mountState(false); const start = (callback)=>{ setPending(true); // Scheduler.unstable_next 通過(guò) transiton 模式,低優(yōu)先級(jí)調(diào)度執(zhí)行回調(diào)函數(shù) // 可以降低更新的優(yōu)先級(jí)。如果回調(diào)中觸發(fā)的更新優(yōu)先級(jí)會(huì)比較低, // 它會(huì)讓位為高優(yōu)先級(jí)的更新,或者當(dāng)前事務(wù)繁忙時(shí),調(diào)度到下一空閑期再應(yīng)用。 Scheduler.unstable_next(() => { const prevTransition = ReactCurrentBatchConfig.transition; ReactCurrentBatchConfig.transition = 1; try { setPending(false); //實(shí)行回調(diào)函數(shù) callback(); } finally { ReactCurrentBatchConfig.transition = prevTransition; } }) } return [isPending, start]; }
startTransition
執(zhí)行過(guò)程中,會(huì)觸發(fā)兩次setPending ,一次在transition=1
之前,一次在之后。startTransition
被調(diào)用時(shí)setPending(true)
,當(dāng)startTransition
內(nèi)部的回調(diào)函數(shù)執(zhí)行時(shí)transiton
過(guò)渡任務(wù)更新setPending(false)
。react內(nèi)部可以根據(jù)pending值的變化準(zhǔn)確把握等待的過(guò)渡時(shí)間,并依此判斷是否超過(guò)了timeoutMs
(如果有傳入)強(qiáng)制執(zhí)行更新。
5. useDeferredValue
useDeferredValue使用介紹
const [value, setValue] = useState('') // defferedValue值延后于state更新 const deferredValue = useDeferredValue(value, {timeoutMs: 2000})
useDeferredValue 返回一個(gè)延遲響應(yīng)的狀態(tài),可以設(shè)置最長(zhǎng)延遲時(shí)間timeoutMs
。
可以傳入可選的timeoutMs,如果給定的timeoutMs內(nèi)未完成,它將會(huì)強(qiáng)制更新。
與useTransition的不同: useTransition是處理一段邏輯
,而useDeferred是產(chǎn)生一個(gè)新?tīng)顟B(tài)
。
useDeferredValue的使用
import React, { useEffect, useState, useTransition, useDeferredValue } from 'react'; import './App.css' const SearchResult = (props) => { const resultList = props.query ? Array.from({ length: 10000 }, (_, index) => ({ id: index, keyword: `${props.query} -- 搜索結(jié)果${index}`, })) : []; return resultList.map(({ id, keyword }) => ( <li key={id}>{keyword}</li> )) } const App = () => { const [value, setValue] = useState(''); const searchValue = useDeferredValue(value, { timeoutMs: 2000 }); useEffect(() => { console.log('對(duì)輸入框值的響應(yīng)--------' + value + '---------------') }, [value]) useEffect(() => { // 監(jiān)聽(tīng)搜索值改變 console.log('對(duì)搜索值的更新響應(yīng)++++++' + searchValue + '+++++++++++') }, [searchValue]) return ( <div className='App'> <input value={value} onChange={e => setValue(e.target.value)} /> <div className={`type_button type_button_checked`}>useDeferredValue</div> <ul> <SearchResult query={searchValue}></SearchResult> </ul> </div> ); };
useDeferredValue簡(jiǎn)單分析
我們通過(guò)偽代碼理解下useDeferredValue
。
function useDeferredValue(value){ const [prevValue, setValue] = updateState(value); updateEffect(() => { // 在 useEffect 中通過(guò) transition 模式來(lái)更新 value 。 Scheduler.unstable_next(() => { const prevTransition = ReactCurrentBatchConfig.transition; ReactCurrentBatchConfig.transition = 1; try { setValue(value); } finally { ReactCurrentBatchConfig.transition = prevTransition; } }) }, [value]); return prevValue; }
useDeferredValue
通過(guò)useEffect監(jiān)聽(tīng)傳入值的變化,然后通過(guò)過(guò)渡任務(wù)執(zhí)行值的改變。這樣保證defrredValue的更新滯后于setState
,同時(shí)符合過(guò)渡更新的原則,因?yàn)槭峭ㄟ^(guò)transition 調(diào)度機(jī)制執(zhí)行的。
關(guān)于“react18中的Transition怎么用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。