如何在React并发模式下实现预取模式

最近,React宣布了React生态系统的一个功能- 并发模式 。 这将使我们能够在所需的时间内停止或延迟组件的执行。 它将帮助React应用程序保持响应速度,并优雅地适应用户的设备功能和网络速度。

并发模式包含一组新功能,其中最大的功能之一就是Suspense和一种新的数据获取方法。

基本上,有三种方法可以做到:

  • 渲染时获取:我们开始渲染组件,并且每个组件都可能触发其效果和生命周期方法中的数据获取。 这方面的一个很好的例子是fetchuseEffect
  • 提取然后呈现:尽快开始获取下一个屏幕的所有数据。 数据准备好后,渲染新屏幕。 数据到达之前我们什么也做不了。 这样的例子是拥有一个Container组件,该组件处理数据获取并在我们收到所有信息后有条件地呈现子表示组件。
  • 渲染-随你取:开始获取全部为下一个画面所需要的数据尽早,并立即开始呈现新的屏幕,即使我们拿到了入网响应 。 随着数据流的进入,React重试渲染仍需要数据的组件,直到它们准备就绪为止。

我相信前两种方法的概念是众所周知的,并且肯定会在您的代码中提出。 让我们直接了解按需渲染   方法。

按需渲染

您可能已经注意到,这种方法的解释包括两个部分:

  1. 尽早开始加载数据。
  2. 开始尝试渲染可能仍需要数据的组件。

早取

让我们一起构建一个加载主要股票指数的应用程序。 为此,我们有一个简单的“加载”按钮。 单击它后,我们将立即开始加载数据:

const App = () => {
  const [prefetchedIndexes, setPrefetchedIndexes] = useState();

  return (
    <>
       <button
        onClick={() => {
            setPrefetchedIndexes(prefetchQuery(`${API}/majors-indexes`));
        }}
      >
        Load all indexes
      </button> 
      {prefetchedIndexes && (
           <IndexList prefetchedIndexes={prefetchedIndexes} />
      )}
    </>
  );
};

prefetchQuery是执行fetch请求并返回要传递给<IndexList />组件的对象的函数。 此示例的关键之处在于,我们是从onClick事件而不是在渲染阶段触发获取的。

提前悬念渲染

上面示例的第二部分是我们将对象从prefetchQuery保存到状态,并立即开始呈现<IndexList />

另一方面,我们也不想用空数据渲染列表,因此理想情况下,我们希望能够暂停渲染,直到我们拥有所有数据而不编写if (isLoading) return null

幸运的是,我们 悬疑 成分正是出于这个目的。

Suspense是一种机制,用于使数据获取库与React进行通信,以告知组件正在读取的数据尚未准备好

然后,React可以等待它准备就绪并更新UI。

让我给你看一个例子:

const IndexList = ( { prefetchedIndexes } ) => {
  const data = usePrefetchedQuery(prefetchedIndexes);

  return data.majorIndexesList.map( index => (
    < div key = {index.ticker} >
      Show {index.ticker}
    </ div >
  ));
};

const App = () => {
  const [prefetchedIndexes, setPrefetchedIndexes] = useState();

  return (
    <>
       <button
        onClick={() => {
            setPrefetchedIndexes(prefetchQuery(`${API}/majors-indexes`));
        }}
      >
        Load all indexes
      </button> 
      {prefetchedIndexes && (
         <Suspense fallback={<span>Loading indexes list...</span>}>
          <IndexList prefetchedIndexes={prefetchedIndexes} />
        </Suspense>
      )}
    </>
  );
};

要利用Suspense,您只需要用它包装您的组件。 它接受一个fallback支持:等待数据时要显示的元素。

如何与暂停同步获取数据?

既然您已经了解了暂挂和预取实践,那么您想知道这是如何协同工作的。 所以,这是这个难题的最后一步。 为了解决这个问题,让我们最后检查一下prefetchQuery函数。

function wrapPromise ( promise )  {
  let status = "pending" ;
  let result;
  let suspender = promise.then(
    r => {
      status = "success" ;
      result = r;
    },
    e => {
      status = "error" ;
      result = e;
    }
  );
  return {
    read() {
      if (status === "pending" ) {
        throw suspender;
      } else if (status === "error" ) {
        throw result;
      } else if (status === "success" ) {
        return result;
      }
    }
  };
}

// Function that reads resource object
// It could also include Cache logic
export const usePrefetchedQuery = prefetchedQuery => prefetchedQuery.read();

export const prefetchQuery = ( input, init ) => {
  // Make fetch request
  const promise = fetch(input, init).then( response => response.json());

  // Return resource for Suspense
  return wrapPromise(promise);
};

不要担心它的复杂性,它实际上很简单。

首先,我们获取一个URL并将其传递给本机fetch wrapPromise函数,接收一个wrapPromise ,然后将其传递给wrapPromise函数。

此函数使用read()方法返回一个对象:

  • 如果仍未兑现承诺,我们将兑现该承诺。
  • 如果一个承诺被错误解决,我们就会抛出错误。
  • 如果诺言得以解决,则只需返回数据即可。

实际上,与传统的获取操作相比,我们唯一的区别是即将实现的承诺。

当你有usePrefetchedQueryIndexList ,它只是执行read()方法。 如果还没有数据,它会在实际呈现任何内容之前抛出一个承诺, Suspense会抓住它。

如何尝试呢?

React团队引入 releases branch with a modern API. experimental releases branch with a modern API.

为此,您需要运行npm i react@experimental react-dom@experimental并在本地使用它。 我还为您在CodeSandbox上创建了一个实时示例,该示例显示了我在一个工作项目中共同完成的所有工作。

我可以在我的生产项目中使用它吗?

否。并发模式仍在开发中,某些实现细节可能会更改。 使用实验版本熟悉新概念,并提出自己的想法。

例如,如何在路由器中集成预取实践或提供缓存数据的好方法。

更多资源

From: https://hackernoon.com/implementing-the-prefetch-pattern-in-react-concurrent-mode-h4r3twc

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值