>首页> IT >

浅析react18中的新概念Transition

时间:2022-03-25 10:57:39       来源:转载
本篇文章带大家了解一下react18的新概念Transition,简单介绍一下新API:startTransition和新hooks:useTransition和usedeferredValue的使用方法,希望对大家有所帮助!

React 18中,引入了一个新概念——transition,由此带来了一个新的API——startTransition和两个新的hooks——useTransitionusedeferredValue,本文由此展开使用尝鲜介绍。【相关推荐: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 }) => (        
  • {keyword}
  • ))}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 (
    setValue(e.target.value)} />
    setTpye(1)}>normal
    setTpye(2)}>transiton
    );};

    普通模式下

    如图所示:连续输入字符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 }) => (        
  • {keyword}
  • ))}const App = () => { const [value, setValue] = useState(""); const searchValue = useDeferredValue(value, { timeoutMs: 2000 }); useEffect(() => { console.log("对输入框值的响应--------" + value + "---------------") }, [value]) useEffect(() => { // 监听搜索值改变 console.log("对搜索值的更新响应++++++" + searchValue + "+++++++++++") }, [searchValue]) return (
    setValue(e.target.value)} />
    useDeferredValue
    );};

    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中文网其它相关文章!

    关键词: 搜索结果 回调函数 输入字符