【问题标题】:React suspense usageReact 悬念用​​法
【发布时间】:2026-01-26 08:35:01
【问题描述】:

假设fetchUserProfile 在别处定义。 Suspense 的使用有什么问题吗?

import { Suspense, useState, useEffect } from 'react';

const SuspensefulUserProfile = ({ userId }) => {
  const [data, setData] = useState({});
  useEffect(() => {
    fetchUserProfile(userId).then((profile) => setData(profile));
  }, [userId, setData])
  return (
    <Suspense>
      <UserProfile data={data} />
    </Suspense>
  );
};
const UserProfile = ({ data }) => {
  return (
    <>
      <h1>{data.name}</h1>
      <h2>{data.email}</h2>
    </>
  );
};
const UserProfileList = () => (
  <>
    <SuspensefulUserProfile userId={1} />
    <SuspensefulUserProfile userId={2} />
    <SuspensefulUserProfile userId={3} />
  </>
);

【问题讨论】:

  • 您希望这个&lt;Suspense&gt; 做什么?如果这就是您的意思,它根本不会与 fetchUserProfile 交互。
  • 我是 Suspense 的新手,请您纠正我在使用 suspense 时所做的事情吗?
  • 你的目标是什么?一旦我知道您要做什么,我就可以就如何做到这一点给您建议,而且很有可能建议是根本不使用 Suspense。您是否尝试在加载过程中加载数据并显示占位符?
  • 是的,等待加载并显示微调器,但使用悬念
  • 为什么要为此使用悬念?我强烈建议你不要使用 suspense 来加载数据,除非你真的知道自己在做什么。

标签: reactjs react-hooks react-suspense


【解决方案1】:

正如 cmets 中所讨论的,我建议您不要为此使用悬念。 Suspense for data loading 是一个实验性功能,如果你不明白到底发生了什么,你可以束手无策。

实现这样的事情的标准方法与您现在拥有的差不多,除了删除悬念并检查空状态。例如:

const DataLoader = ({ userId }) => {
  const [data, setData] = useState(null);
  useEffect(() => {
    fetchUserProfile(userId).then((profile) => setData(profile));
  }, [userId, setData])

  if (data === null) {
    return <div>Loading...</div>
  }
  return (
    <UserProfile data={data} />
  );
};

如果你想使用悬念,你需要颠倒你做事的方式。 Suspense 需要在进行数据加载的组件之外,然后你需要抛出一个 Promise 来告诉 suspense 正在加载:

const OuterComponent = () => {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <DataLoader />
    </Suspense>
  );
}

let data;

const DataLoader = () => {
  if (!data) {
    throw fetchUserProfile(userId)
      .then((profile) => { data = profile });
  }

  return <UserProfile data={data} />
}

请注意,数据需要在组件之外,因为一旦 promise 解决,suspense 将尝试再次渲染组件并且您的数据必须同步可用,否则您将抛出另一个 promise 并输入无限循环。

【讨论】: