我正在尝试使用
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 调用完成,如文档中所述。我是不是做错了什么?
useTransition
文档:
参数
:一种通过调用一个或多个action
函数来更新某些状态的函数。 React 立即不带参数调用set
,并将在action
函数调用期间同步安排的所有状态更新标记为 Transitions。在action
中等待的任何异步调用都将包含在 Transition 中,但目前需要将action
之后的任何set
函数包装在额外的await
中(请参阅故障排除)。标记为转换的状态更新将是非阻塞的,并且不会显示不需要的加载指示器。startTransition
故障排除部分的进一步内容:
React 不会将
之后的状态更新视为 Transitionawait
当您在
函数中使用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);
});
});
};