代码之家  ›  专栏  ›  技术社区  ›  Ali Navidi

为什么在使用计算量大的useTransition时isPending没有立即变为true?

  •  0
  • Ali Navidi  · 技术社区  · 6 月前

    我正在测试一个繁重的计算,它会阻止我的UI的渲染,并使用 useTransition 钩子来修复它,并在更新时显示加载情况。

    附录tsx

    import { useEffect, useState, useTransition } from "react";
    import "./styles.css";
    
    export default function App() {
      const [count, setCount] = useState(0);
      const [isPending, startTransition] = useTransition();
    
      const handleClick = () => {
        console.log("Starting Transition...");
        startTransition(() => {
          for (let i = 0; i < 1000000000; i++) {}
          setCount((prevCount) => prevCount + 1);
          console.log("Ending Transition...");
        });
      };
    
      useEffect(() => {
        console.log(isPending);
      }, [isPending]);
    
      return (
        <div className="App">
          <div>
            <h1>{count}</h1>
            <button disabled={isPending} onClick={handleClick}>
              {isPending ? "Loading..." : "Increment"}
            </button>
          </div>
          {isPending && "Loading"}
        </div>
      );
    }
    

    问题是 isPending 在事件发生后不久,它就变成了真 使用转换 当我点击按钮时,日志如下:

    日志

    Starting Transition...
    Ending Transition...
    true
    false
    

    我的问题是为什么 待定 当过渡开始时,而不是结束后,这不是真的吗?

    1 回复  |  直到 6 月前
        1
  •  1
  •   Nicholas Tower    6 月前

    startTransition 调用时不会导致同步重解码器。同步重解码器是 a thing that exists ,但它们可能是一个性能问题,过渡正试图 改善 感知性能,而不是伤害它。

    相反,当你打电话的时候 startTransition 你告诉react“我在这个函数中设置状态的任何调用都是低优先级的”。React会注意到这一点,然后调用你的函数,然后你可以随意设置状态。一旦你的函数返回,react就会排队等待一个正常的优先级重置器来设置 isPending 真的。之后,它会进行低优先级渲染以应用您所做的状态更改。

    所以 startTransition 它不是为你做大量同步工作而设计的。它对此毫无帮助。你可以打电话 startTransition 当你 完成 但这很有用,不是因为它破坏了同步代码,而是因为结果呈现的优先级很低。如果渲染本身可能需要一段时间,或者如果你预计用户会做你不想放慢速度的高优先级事情(例如,在输入字段中键入),那么低优先级渲染是有用的。

    如果你想拆分一些同步代码,你必须编写自定义代码来实现这一点。例如,您可以有一系列 setTimeout s每个都运行一段代码,然后排队等待下一个setTimeout,从而让浏览器有机会运行其他代码。