本篇文章帶大家了解react18的新概念Transition,簡單介紹一下新API:startTransition和新hooks:useTransition和usedeferredValue的使用方法,希望對大家有幫助!
React 18中,引入了一個新概念-transition
,由此帶來了一個新的API-startTransition
和兩個新的hooks——useTransition
和usedeferredValue
,本文由此展開使用嚐鮮介紹。 【相關推薦:Redis影片教學】
1. 總覽表
本文分為4部分進行:
tansition
產生初衷startTransition
使用與介紹 使用與介紹
使用和介紹
#2. transition產生初衷
#transtion 直接翻譯為
過渡。 tansition本質上是
為了解決渲染並發問題所提出。在React中一旦元件狀態改變並觸發了重新渲染,則無法停止渲染。直到元件重新渲染完畢,頁面才能繼續回應使用者的互動。
(urgent update):使用者期望馬上回應的更新操作,例如滑鼠單擊或鍵盤輸入。
(transition update):一些延遲可以接受的更新操作,如查詢時,搜尋推薦、搜尋結果的展示等。
// 被startTransiton标记后为过渡更新 startTransition(()=> { // 非紧急更新,会被降低优先级,延迟执行 setQueryValue(inputValue) }) // 未被标记则马上执行 setInputValue(inputValue)
startTrionstion標記的更新,即為過渡更新(執行的優先權被降低),此時react會根據內部的調度機制延遲執行內部的state更新。
透過區分更新優先權,讓高優先權的事件保持回應,
提高使用者互動體驗,維持頁面響應。
3. startTransiton
#startTransiton使用介紹
const handleClick = () => { // startTransition包裹标记为低优先级更新 startTransition(()=> { setQueryValue(inputValue) }) // 未被标记则马上执行 setInputValue(inputValue) }
startTransition
透過示範對比
#這是一個對輸入字元後展示搜尋結果的場景模擬,透過偽造大量搜尋結果,模擬容易卡頓的情況。 我們試著連續輸入123,監聽搜尋框值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} -- 搜索结果${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(() => { // 监听搜索值改变 console.log('对搜索值更新的响应++++++' + searchVal + '+++++++++++') }, [searchVal]) useEffect(() => { console.log('对输入框值更新的响应-----' + 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> ); };
普通模式下
#如圖:連續輸入字元123,當第一個字元輸入後,搜尋值馬上回應,清單渲染立刻開始,造成卡頓輸入框停止了對使用者輸入的回應,直到渲染結束,輸入框才繼續回應。
使用startTransition後
#如圖所示:連續輸入字元123,輸入框不斷回應,搜尋值的回應被延後,保證頁面回饋,直到輸入結束,才開始回應搜尋值,渲染搜尋結果,保持頁面回應。
4. useTransiton
#useTransiton使用介紹
import { useTransiton } from 'react' const [isPending, startTransition] = useTransiton({timeoutMs: 2000}) // 例如, 在pending状态下,您可以展示一个Spinner { isPending ? < Spinner /> : null }
是一個接受回呼的函數,用來告知React需要延遲更新的state。
是一個布林值,這是react告知我們是否等待過渡完成的方式。
接受帶有
timeoutMs 的延遲回應的值,如果給定的timeoutMs內未完成,它將會強制執行
startTransition回呼函數內state的更新。
useTransiton簡單分析
我們透過偽代碼理解下useTransition。
function useTransition(){ const [isPending, setPending] = mountState(false); const start = (callback)=>{ setPending(true); // Scheduler.unstable_next 通过 transiton 模式,低优先级调度执行回调函数 // 可以降低更新的优先级。如果回调中触发的更新优先级会比较低, // 它会让位为高优先级的更新,或者当前事务繁忙时,调度到下一空闲期再应用。 Scheduler.unstable_next(() => { const prevTransition = ReactCurrentBatchConfig.transition; ReactCurrentBatchConfig.transition = 1; try { setPending(false); //实行回调函数 callback(); } finally { ReactCurrentBatchConfig.transition = prevTransition; } }) } return [isPending, start]; }
startTransition
执行过程中,会触发两次setPending ,一次在transition=1
之前,一次在之后。startTransition
被调用时setPending(true)
,当startTransition
内部的回调函数执行时transiton
过渡任务更新setPending(false)
。react内部可以根据pending值的变化准确把握等待的过渡时间,并依此判断是否超过了timeoutMs
(如果有传入)强制执行更新。
5. useDeferredValue
useDeferredValue使用介绍
const [value, setValue] = useState('') // defferedValue值延后于state更新 const deferredValue = useDeferredValue(value, {timeoutMs: 2000})
timeoutMs
。一段逻辑
,而useDeferred是产生一个新状态
。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} -- 搜索结果${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('对输入框值的响应--------' + value + '---------------') }, [value]) useEffect(() => { // 监听搜索值改变 console.log('对搜索值的更新响应++++++' + 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简单分析
我们通过伪代码理解下useDeferredValue
。
function useDeferredValue(value){ const [prevValue, setValue] = updateState(value); updateEffect(() => { // 在 useEffect 中通过 transition 模式来更新 value 。 Scheduler.unstable_next(() => { const prevTransition = ReactCurrentBatchConfig.transition; ReactCurrentBatchConfig.transition = 1; try { setValue(value); } finally { ReactCurrentBatchConfig.transition = prevTransition; } }) }, [value]); return prevValue; }
useDeferredValue
通过useEffect监听传入值的变化,然后通过过渡任务执行值的改变。这样保证defrredValue的更新滞后于setState
,同时符合过渡更新的原则,因为是通过transition 调度机制执行的。
更多编程相关知识,请访问:编程视频!!
以上是淺析react18中的新概念Transition的詳細內容。更多資訊請關注PHP中文網其他相關文章!