浅析react18中的新概念Transition
React 18中,引入了一个新概念——transition,由此带来了一个新的API——startTransition和两个新的hooks——useTransition和usedeferredValue,本文由此展开使用尝鲜介绍。【相关推荐:Redis视频教程】
1. 总览
本文分为4部分进行:
tansition产生初衷startTransition使用和介绍useTransition使用和介绍useDeferredValue使用和介绍
2. transition产生初衷
transtion 直接翻译为 过渡。tansition本质上是为了解决渲染并发问题所提出。在React中一旦组件状态改变并触发了重新渲染,则无法停止渲染。直到组件重新渲染完毕,页面才能继续响应用户的交互。
为此react 18中更新都可以划分为以下两类:
紧急更新(urgent update):用户期望马上响应的更新操作,例如鼠标单击或键盘输入。过渡更新(transition update):一些延迟可以接受的更新操作,如查询时,搜索推荐、搜索结果的展示等。
// 被startTransiton标记后为过渡更新startTransition(()=>
{
// 非紧急更新,会被降低优先级,延迟执行 setQueryValue(inputValue)}
)// 未被标记则马上执行setInputValue(inputValue)在react 18中被startTrionstion标记的更新,即为过渡更新(执行的优先级被降低),此时react会根据内部的调度机制延迟执行内部的state更新。
开发中开发者可以通过transition hook决定哪些更新被标记为transition事件。一旦被标记则代表为低优先级执行,即react知道该state可以延迟更新,通过区分更新优先级,让高优先级的事件保持响应,提高用户交互体验,保持页面响应。
3. startTransiton
startTransiton使用介绍
const handleClick = () =>
{
// startTransition包裹标记为低优先级更新 startTransition(()=>
{
setQueryValue(inputValue) }
) // 未被标记则马上执行 setInputValue(inputValue)}
首先我们来介绍下最简单的startTransition
- startTransiton 是一个接受回调的函数,用于告知React需要延迟更新的state。
- 如果某个state的更新会导致组件挂起,则应该包裹在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 }
startTransition是一个接受回调的函数,用于告知React需要延迟更新的state。isPending是一个布尔值,这是react告知我们是否等待过渡完成的方式。useTransition接受带有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}
)- useDeferredValue 返回一个延迟响应的状态,可以设置最长延迟时间
timeoutMs。 - 可以传入可选的timeoutMs,如果给定的timeoutMs内未完成,它将会强制更新。
- 与useTransition的不同: useTransition是处理
一段逻辑,而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的详细内容,更多请关注其它相关文章!
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 浅析react18中的新概念Transition
本文地址: https://pptw.com/jishu/593713.html
