在 React 18 中,useEffect 的函数是否保证在 Suspense Promise 完成后运行?

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

我有一个简单的主从场景,在左侧,我使用

useSwr
和 REST 服务加载城市列表,然后在右侧我有一个城市详细信息窗口,它也使用
useSwr
加载城市列表单个城市(从左侧单击或首次加载)。

在下面的代码中,我调用 useEffect 函数,然后在状态设置调用 (setSelectedCityId) 中使用从

useSwr
检索的数据。

这是可行的,并且始终存在与城市数组相关的数据,但我想知道是否可以保证 useEffect 的函数将在 Suspense Promise 完成后运行(就像看起来的那样)。

这是我的简单代码:

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 调用。

reactjs react-hooks swr react-suspense
1个回答
5
投票

是的,在 React 18 中,当树一致时,

useEffect
总是运行。因此,只有在树准备好且未暂停后才会触发效果。

© www.soinside.com 2019 - 2024. All rights reserved.