在 React 18 中,useEffect 的功能是否保证在 Suspense 承诺完成后 运行?
In React 18, is useEffect's function guaranteed to run AFTER a Suspense promise completes?
我有一个简单的主从场景,在左侧,我使用 useSwr
和 REST 服务加载城市列表,然后在右侧我有一个城市详细信息 windows 也使用 useSwr
加载单个城市(从左侧单击或第一次加载)。
在下面的代码中,我调用了 useEffect 函数,然后在状态设置调用 (setSelectedCityId) 中使用从 useSwr
检索到的数据。
这行得通,并且一直有与城市数组相关联的数据,但我想知道是否可以保证 useEffect 的函数将 运行 在 Suspense 承诺完成后(看起来像).
这是我的简单代码:
import { Suspense, useEffect, useState, useTransition } from "react";
import useSwr from "swr";
const fetcher = (...args) => fetch(...args).then((res) => res.json());
function CityDetailFallback() {
return <div>Loading (CityDetail)</div>;
}
function CityDetail({ selectedCityId }) {
function CityDetailUI({ selectedCityId }) {
const { data: city } = useSwr(
selectedCityId
? `http://localhost:3000/api/city/${selectedCityId}`
: null,
fetcher,
{
suspense: true,
}
);
if (!city) {
return <div>loading city...</div>
}
return (
<div className="row">
<div className="col-9">
<div>{JSON.stringify(city)} </div>
</div>
</div>
);
}
return (
<Suspense fallback={<CityDetailFallback />}>
<CityDetailUI selectedCityId={selectedCityId}></CityDetailUI>
</Suspense>
);
}
function CityList({
setSelectedCityId
}) {
//
const { data: cities } = useSwr("http://localhost:3000/api/city", fetcher, {
suspense: true,
});
useEffect(() => {
setSelectedCityId(cities[0].id);
}, []);
return (
<div className="col-3">
{cities.map((city) => {
return (
<div key={city.id}>
<button
onClick={(e) => {
setSelectedCityId(city.id);
}}
>
{city.city}
</button>
</div>
);
})}
</div>
);
}
export default function App() {
const [selectedCityId, setSelectedCityId] = useState();
return (
<div className="container">
<a href="/">Site Root</a>
<hr />
<Suspense fallback={<div>Loading...</div>}>
<div className="row">
<div className="col-3">
<b>CITY LIST</b>
<hr />
<CityList
setSelectedCityId={setSelectedCityId}
selectedCityId={selectedCityId}
/>
</div>
<div className="col-9">
<div>
<b>CITY DETAIL (TOP ROW SELECTED AUTOMATICALLY)</b>
<hr />
<CityDetail selectedCityId={selectedCityId} />
</div>
</div>
</div>
</Suspense>
</div>
);
}
注意:由于 useSwr 中的当前错误,我无法创建代码沙箱。 https://github.com/vercel/swr/issues/1906 我目前正在使用 Create React App 进行测试,并使用虚拟 api 端点进行 REST 调用。对不起:(
是的,在 React 18 中 useEffect
总是在树一致时运行。因此只有在树准备好且未挂起后才会触发效果。
我有一个简单的主从场景,在左侧,我使用 useSwr
和 REST 服务加载城市列表,然后在右侧我有一个城市详细信息 windows 也使用 useSwr
加载单个城市(从左侧单击或第一次加载)。
在下面的代码中,我调用了 useEffect 函数,然后在状态设置调用 (setSelectedCityId) 中使用从 useSwr
检索到的数据。
这行得通,并且一直有与城市数组相关联的数据,但我想知道是否可以保证 useEffect 的函数将 运行 在 Suspense 承诺完成后(看起来像).
这是我的简单代码:
import { Suspense, useEffect, useState, useTransition } from "react";
import useSwr from "swr";
const fetcher = (...args) => fetch(...args).then((res) => res.json());
function CityDetailFallback() {
return <div>Loading (CityDetail)</div>;
}
function CityDetail({ selectedCityId }) {
function CityDetailUI({ selectedCityId }) {
const { data: city } = useSwr(
selectedCityId
? `http://localhost:3000/api/city/${selectedCityId}`
: null,
fetcher,
{
suspense: true,
}
);
if (!city) {
return <div>loading city...</div>
}
return (
<div className="row">
<div className="col-9">
<div>{JSON.stringify(city)} </div>
</div>
</div>
);
}
return (
<Suspense fallback={<CityDetailFallback />}>
<CityDetailUI selectedCityId={selectedCityId}></CityDetailUI>
</Suspense>
);
}
function CityList({
setSelectedCityId
}) {
//
const { data: cities } = useSwr("http://localhost:3000/api/city", fetcher, {
suspense: true,
});
useEffect(() => {
setSelectedCityId(cities[0].id);
}, []);
return (
<div className="col-3">
{cities.map((city) => {
return (
<div key={city.id}>
<button
onClick={(e) => {
setSelectedCityId(city.id);
}}
>
{city.city}
</button>
</div>
);
})}
</div>
);
}
export default function App() {
const [selectedCityId, setSelectedCityId] = useState();
return (
<div className="container">
<a href="/">Site Root</a>
<hr />
<Suspense fallback={<div>Loading...</div>}>
<div className="row">
<div className="col-3">
<b>CITY LIST</b>
<hr />
<CityList
setSelectedCityId={setSelectedCityId}
selectedCityId={selectedCityId}
/>
</div>
<div className="col-9">
<div>
<b>CITY DETAIL (TOP ROW SELECTED AUTOMATICALLY)</b>
<hr />
<CityDetail selectedCityId={selectedCityId} />
</div>
</div>
</div>
</Suspense>
</div>
);
}
注意:由于 useSwr 中的当前错误,我无法创建代码沙箱。 https://github.com/vercel/swr/issues/1906 我目前正在使用 Create React App 进行测试,并使用虚拟 api 端点进行 REST 调用。对不起:(
是的,在 React 18 中 useEffect
总是在树一致时运行。因此只有在树准备好且未挂起后才会触发效果。