useTransition 的 isPending 在更改为 false 之前不等待 API 调用完成

问题描述 投票:0回答:1

我正在尝试使用

useTransition
钩子解决问题。我有一个按钮,它的
onClick
会触发一个进行 API 调用的函数。问题在于,在 API 调用完成之前,
isPending
钩子中的
useTransition
设置为 false。

function App() {
  const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
  const [isPending, startTransition] = useTransition();
  const [data, setData] = useState(null);
  useEffect(()=>{
    console.log("Is Pending changed", isPending)
  },[isPending])
  const fetchData = async () => {
    startTransition(async () => {
      await delay(2000);
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); // Replace with your API endpoint
      const result = await response.json();
      setData(result);
    });
  };

  return (
    <div>
      <button onClick={fetchData}>Fetch Data</button>
      {isPending ? (
        <p>Fetching data...</p>
      ) : (
        data && <pre>{JSON.stringify(data, null, 2)}</pre>
      )}
    </div>
  );

}

我希望

useTransisition
应等待 API 调用完成,如文档中所述。我是不是做错了什么?

reactjs react-hooks
1个回答
0
投票

来自

useTransition
文档

参数

action
:一种通过调用一个或多个
set
函数来更新某些状态的函数。 React 立即不带参数调用
action
,并将在
action
函数调用期间同步安排的所有状态更新标记为 Transitions。在
action
中等待的任何异步调用都将包含在 Transition 中,但目前需要将
set
之后的任何
await
函数包装在额外的
startTransition
中(请参阅故障排除)。标记为转换的状态更新将是非阻塞的,并且不会显示不需要的加载指示器。

故障排除部分的进一步内容:

React 不会将
await
之后的状态更新视为 Transition

当您在

await
函数中使用
startTransition
时,
await
之后发生的状态更新不会标记为转换。您必须在
await
调用中的每个
startTransition
之后包装状态更新:

startTransition(async () => {
  await someAsyncFunction();
  // ❌ Not using startTransition after await
  setPage('/about');
});

然而,这却有效:

startTransition(async () => {
  await someAsyncFunction();
  // ✅ Using startTransition *after* await
  startTransition(() => {
    setPage('/about');
  });
});

这是 JavaScript 的限制,因为 React 失去了范围 异步上下文。将来,当 AsyncContext 可用时,这 限制将被取消。

因此,要在转换后更新您的状态,请将代码更改为:

  const fetchData = async () => {
    startTransition(async () => {
      await delay(2000);
      const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); // Replace with your API endpoint
      const result = await response.json();
      startTransition(() => {
        setData(result);
      });
    });
  };
© www.soinside.com 2019 - 2024. All rights reserved.