How to quickly get started with VUE3.0: Entering to learn
React 18, a new concept - transition
is introduced, which brings a new API - startTransition
and two new hooks - useTransition
and usedeferredValue
. This article starts from here Use early adopter introductions.
1. Overview
This article is divided into four parts:
tansition
,startTransition
useTransition
,useDeferredValue
2. The original intention of transition,
transtion
is directly translated as过渡
. tansition is essentially为了解决渲染并发问题所提出
. In React, once the component state changes and a re-render is triggered, rendering cannot be stopped. The page cannot continue to respond to user interaction until the component is re-rendered.
For this reason, updates in react 18 can be divided into the following two categories:
紧急更新
: update operations that users expect to respond immediately, such as mouse clicks or keyboard input.过渡更新
: some update operations with acceptable delay, such as query, search recommendation, display of search results, etc.// Update startTransition(()=> { after being marked by startTransiton for transition // Non-urgent updates will be lowered in priority and the execution of setQueryValue(inputValue) will be delayed. }) // If it is not marked, setInputValue(inputValue) will be executed immediately.
The update marked by startTrionstion
in react 18 is a transitional update (the execution priority is reduced). At this time, react will delay the execution of the internal state update according to the internal scheduling mechanism. .
Developers under development can decide which updates are marked as transition events through transition hooks. Once marked, it represents a low-priority execution, that is, React knows that the state can be delayed in updating.通过区分更新优先级
, high-priority events can remain responsive,提高用户交互体验,保持页面响应
.
3. startTransiton
startTransiton usage introduction
const handleClick = () => { // startTransition package marked as low priority update startTransition(()=> { setQueryValue(inputValue) }) // If it is not marked, setInputValue(inputValue) will be executed immediately }
First, let’s introduce the simplest startTransition.
Through demonstration and comparison,
this is a scenario simulation of displaying search results after entering characters. By forging a large number of search results, it simulates a situation that is prone to freezing.
We try to continuously input 123, monitor the change of the search box value
(urgent update) and the change of the search value searchVal
(transition update) and output it to the control bar.
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} -- search results${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(() => { // Monitor search value changes console.log('Response to search value update++++++' + searchVal + '++++++++++++') }, [searchVal]) useEffect(() => { console.log('Response to input box value update-----' + 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> ); };
In normal mode
如图所示:
123 characters are entered continuously. When the first character is entered, the search value responds immediately, and the list rendering starts immediately, causing the input box to freeze and stop responding to user input. The input box does not continue to respond until the rendering is completed. .
After using startTransition
如图所示:
Continuously input characters 123, the input box continues to respond, and the response to the search value is delayed to ensure page feedback. It does not start responding to the search value until the end of the input, rendering the search results, and keeping the page responsive.
4. useTransiton
useTransiton usage introduction
import { useTransiton } from 'react' const [isPending, startTransition] = useTransiton({timeoutMs: 2000}) // For example, in the pending state, you can display a Spinner { isPending ? < Spinner /> : null }
startTransition
is a function that accepts a callback and is used to inform React of the state that needs to be delayed.isPending
is a boolean, which is react's way of telling us whether to wait for the transition to complete.useTransition
accepts the value of a delayed response with timeoutMs
. If it is not completed within the given timeoutMs, it will force the update of the state in the startTransition
callback function.Simple analysis of useTransiton
We understand useTransition
through pseudo code.
function useTransition(){ const [isPending, setPending] = mountState(false); const start = (callback)=>{ setPending(true); // Scheduler.unstable_next Through transiton mode, low-priority scheduling execution callback function // can reduce the priority of updates. If the update triggered in the callback has a lower priority, // It will be set to a high-priority update, or when the current transaction is busy, it will be scheduled to be applied in the next idle period. Scheduler.unstable_next(() => { const prevTransition = ReactCurrentBatchConfig.transition; ReactCurrentBatchConfig.transition = 1; try { setPending(false); //Execute callback function callback(); } finally { ReactCurrentBatchConfig.transition = prevTransition; } }) } return [isPending, start]; }
During the execution of startTransition
, setPending will be triggered twice, once before transition=1
and once after. setPending(true)
when startTransition
is called, and transiton
transition task updates setPending(false)
when the callback function inside startTransition
is executed. React can accurately grasp the waiting transition time based on changes in the pending value, and use this to determine whether timeoutMs
has been exceeded (if any are passed in) to force an update.
5. useDeferredValue
useDeferredValue usage introduction
const [value, setValue] = useState('') // The defferedValue value is delayed after the state update const deferredValue = useDeferredValue(value, {timeoutMs: 2000})
timeoutMs
can be set.一段逻辑
, while useDeferred generates一个新状态
.Use of 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} -- search results${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('Response to input box value--------' + value + '---------------') }, [value]) useEffect(() => { // Monitor search value changes console.log('Update response to search value++++++' + 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> ); };
Simple analysis of useDeferredValue
We understand useDeferredValue
through pseudo code.
function useDeferredValue(value){ const [prevValue, setValue] = updateState(value); updateEffect(() => { // Update value through transition mode in useEffect. Scheduler.unstable_next(() => { const prevTransition = ReactCurrentBatchConfig.transition; ReactCurrentBatchConfig.transition = 1; try { setValue(value); } finally { ReactCurrentBatchConfig.transition = prevTransition; } }) }, [value]); return prevValue; }
useDeferredValue
listens for changes in the incoming value through useEffect, and then performs the value change through the transition task. This保证defrredValue的更新滞后于setState
and conforms to the principle of transitional update because it is executed through the transition scheduling mechanism.