0

假设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} />
  </>
);
4

1 回答 1

1

正如评论中所讨论的,我建议您不要为此使用悬念。数据加载的悬念是一项实验性功能,如果您不了解到底发生了什么,您可以束手无策。

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

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 并进入无限循环。

于 2021-01-21T01:38:18.337 回答