Home  >  Article  >  Web Front-end  >  A brief analysis of the new concept Transition in react18

A brief analysis of the new concept Transition in react18

青灯夜游
青灯夜游forward
2022-03-25 10:52:462446browse

This article will take you to understand the new concept of Transition in react18, and briefly introduce the use of the new API: startTransition and new hooks: useTransition and usedeferredValue. I hope it will be helpful to everyone!

A brief analysis of the new concept Transition in react18

In React 18, a new concept is introduced - transition, which brings a new API - startTransition and two new hooks - useTransition and usedeferredValue, this article starts with an early adopter introduction. [Related recommendations: Redis Video Tutorial]

1. Overview

This article is divided into 4 parts:

  • tansition Original intention
  • startTransition Use and introduction
  • useTransition Use and introduction
  • useDeferredValue Use and introduction

2. Original intention of transition

transtion is directly translated as transition. Tansition is essentially proposed to solve the problem of rendering concurrency. 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:

  • Emergency update (urgent update): update operations that users expect to respond immediately, Such as mouse clicks or keyboard input.
  • Transition update (transition update): Some update operations with acceptable delay, such as query time, search recommendations, display of search results, etc.
// 被startTransiton标记后为过渡更新
startTransition(()=> {
    // 非紧急更新,会被降低优先级,延迟执行
    setQueryValue(inputValue)
})

// 未被标记则马上执行
setInputValue(inputValue)

In react 18, the update marked by startTrionstion is a transitional update (the priority of execution is reduced). At this time, react will delay execution according to the internal scheduling mechanism. Internal state update.

During development, developers 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. By distinguishing the update priority , high-priority events can remain responsive, improve the user interaction experience, and maintain Page response .

3. startTransiton

Introduction to the use of startTransiton

const handleClick = () => {
    // startTransition包裹标记为低优先级更新
    startTransition(()=> {
        setQueryValue(inputValue)
    })
    
    // 未被标记则马上执行
    setInputValue(inputValue)
}

First of all, let’s introduce the simplest The startTransition

  • startTransiton is a function that accepts a callback and is used to tell React that the state needs to be delayed.
  • If a certain state update will cause the component to hang, it should be wrapped in startTransition

Comparison through demonstration

This is a scenario simulation of displaying search results after entering characters. By forging a large number of search results, it simulates the situation where it is easy to freeze.

We try to continuously enter 123, monitor the change of the search box value value (urgent update) and the change of the search value searchVal (transition update) and output them 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} -- 搜索结果${index}`,
        })) : [];
    return resultList.map(({ id, keyword }) => (
        <li key={id}>{keyword}</li>
    ))
}

const App = () => {
    const [type, setTpye] = useState(1)
    const [value, setValue] = useState(&#39;&#39;);
    const [searchVal, setSearchVal] = useState(&#39;-&#39;);

    useEffect(() => {
        // 监听搜索值改变
        console.log(&#39;对搜索值更新的响应++++++&#39; + searchVal + &#39;+++++++++++&#39;)
    }, [searchVal])

    useEffect(() => {
        console.log(&#39;对输入框值更新的响应-----&#39; + value + &#39;-------------&#39;)
        if (type === 1) {
            setSearchVal(value || &#39;-&#39;)
        }
        if (type === 2) {
            startTransition(() => {
                setSearchVal(value || &#39;-&#39;)
            })
       }
    }, [value, type]);

    return (
        <div className=&#39;App&#39;>
            <input value={value} onChange={e => setValue(e.target.value)} />
            <div className={`type_button ${type === 1 ? &#39;type_button_checked&#39; : &#39;&#39;}`} onClick={() => setTpye(1)}>normal</div>
            <div className={`type_button ${type === 2 ? &#39;type_button_checked&#39; : &#39;&#39;}`} onClick={() => setTpye(2)}>transiton</div>
            <ul>
                <SearchResult query={searchVal}></SearchResult>
            </ul>
        </div>
    );
};

In normal mode

A brief analysis of the new concept Transition in react18

As shown in the figure: Enter 123 characters continuously. When the first After characters are entered, the search value responds immediately, and 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

A brief analysis of the new concept Transition in react18

As shown in the figure: Enter 123 characters continuously, and the input box continues to respond , 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 &#39;react&#39;

const [isPending, startTransition] = useTransiton({timeoutMs: 2000})
// 例如, 在pending状态下,您可以展示一个Spinner
{ isPending ? < Spinner /> : null }
  • startTransition is a function that accepts callbacks and is used to inform React of the state that needs to be delayed.
  • isPending is a boolean value, which is react's way of telling us whether to wait for the transition to complete.
  • useTransition Accepts a value with a delayed response of timeoutMs. If it is not completed within the given timeoutMs, it will force the execution of startTransition Update of state within the 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 通过 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(&#39;&#39;)
// defferedValue值延后于state更新
const deferredValue = useDeferredValue(value, {timeoutMs: 2000})
  • useDeferredValue 返回一个延迟响应的状态,可以设置最长延迟时间timeoutMs
  • 可以传入可选的timeoutMs,如果给定的timeoutMs内未完成,它将会强制更新。
  • 与useTransition的不同: useTransition是处理一段逻辑,而useDeferred是产生一个新状态

useDeferredValue的使用

import React, { useEffect, useState, useTransition, useDeferredValue } from &#39;react&#39;;
import &#39;./App.css&#39;

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(&#39;&#39;);
    const searchValue = useDeferredValue(value, { timeoutMs: 2000 });

    useEffect(() => {
        console.log(&#39;对输入框值的响应--------&#39; + value + &#39;---------------&#39;)
    }, [value])

    useEffect(() => {
        // 监听搜索值改变
        console.log(&#39;对搜索值的更新响应++++++&#39; + searchValue + &#39;+++++++++++&#39;)
    }, [searchValue])

    return (
        <div className=&#39;App&#39;>
            <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>
    );
};

A brief analysis of the new concept Transition in react18

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 调度机制执行的。

更多编程相关知识,请访问:编程视频!!

The above is the detailed content of A brief analysis of the new concept Transition in react18. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.cn. If there is any infringement, please contact admin@php.cn delete