繁体   English   中英

了解 Suspense 和 React Hooks

[英]Understanding Suspense and React Hooks

我正在努力寻找使用SuspenseReact hooks的问题。

下面的 React 代码有几个关键问题

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} />
  </>
};

让我知道它们是什么。

我发现了两个关键问题。

  • useEffect依赖数组中滥用setdata
  • 没有提供suspense fallback道具。

我认为还存在一个关键问题。

一件奇怪的事情是为什么userId需要包含在依赖项数组中。

您滥用了Suspense的核心,至少在获取数据的悬念可用之前是这样。

Suspense 目前仅适用于React.lazy组件,不适用于应用程序的任意“加载”状态。 例如,React 应该如何确定您的data正在加载?

Suspense的唯一用途是允许在 React 加载惰性组件时显示一些回退。 对于其他类型的延迟加载应用程序数据,您可以实现自己的回退,如:

const SuspensefulUserProfile = ({ userId }) => {
  const [data, setData] = useState();

  useEffect(() => {
    fetchUserProfile(userId).then(setData);
  }, [userId])

  return data ? <UserProfile data={data} /> : 'Loading...';
};

主要问题是您需要使用所谓的Suspense 集成来执行数据获取和与<Suspense>组件的交互。

通常<UserProfile>组件会同步使用资源(在本例中为您的data )并在资源不可用时暂停组件,导致<Suspense>暂时呈现其fallback道具(您尚未指定)。 当资源可用时, <UserProfile>会重新渲染,并同步返回消耗的资源。

我发布了一个名为suspense-service的 Suspense 集成,它允许您使用封装 React上下文 API的服务来使用异步 function 定义的资源。

通过稍微修改您的示例代码,下面是suspense-service的演示:

 // import { Fragment, Suspense } from 'react'; const { Fragment, Suspense } = React; // import { createService, useService } from 'suspense-service'; const { createService, useService } = SuspenseService; const fetchUserProfile = userId => { return new Promise(resolve => { setTimeout(resolve, 1000 + Math.random() * 1000); }).then(() => { return { name: `User ${userId}`, email: `user${userId}@example.com` }; }); }; const UserProfileService = createService(fetchUserProfile); const SuspensefulUserProfile = ({ userId }) => { return ( <UserProfileService.Provider request={userId}> <Suspense fallback={<h1>Loading User Profile...</h1>}> <UserProfile /> </Suspense> </UserProfileService.Provider> ); }; const UserProfile = () => { const data = useService(UserProfileService); return ( <Fragment> <h1>{data.name}</h1> <h2>{data.email}</h2> </Fragment> ); }; const UserProfileList = () => { return ( <Fragment> <SuspensefulUserProfile userId={1} /> <SuspensefulUserProfile userId={2} /> <SuspensefulUserProfile userId={3} /> </Fragment> ); }; ReactDOM.render(<UserProfileList />, document.getElementById('root'));
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/suspense-service@0.2.3"></script> <div id="root"></div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM