React Suspense 尝鲜

栏目: IOS · Android · 发布时间: 7年前

内容简介:如同字面意思,Suspense 让组件遇到异步操作时进入“悬停”状态,等异步操作有结果时再回归正常状态。异步操作简单归为两类:异步加载代码就是所谓的

如同字面意思,Suspense 让组件遇到异步操作时进入“悬停”状态,等异步操作有结果时再回归正常状态。

异步操作简单归为两类:

  1. 异步加载代码
  2. 异步加载数据

异步加载代码

异步加载代码就是所谓的 code splitting ,实现起来就像是这样:

import React, {lazy, Suspense} from 'react';

const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />
    </Suspense>
  );
}
复制代码

值得一提的是目前版本 (截止至 react@16.8) 还不支持服务端渲染,但还是会在以后的版本上支持的。

异步加载数据

Suspense 异步加载数据截止到目前都是不稳定的版本,根据React 16.x Roadmap,大概到2019年中期发布稳定版本,但是 React 官方提供了一个独立的包 react-cache ,使用它结合 react@16.6.0 可以让我们提前感受一下 Suspense 异步加载数据。

import { unstable_createResource } from 'react-cache';

const getSomething = (something) => new Promise((resolve) => {
  setTimeout(() => {
    resolve(something);
  }, 1000);
})

const resource = unstable_createResource((id) => getSomething(id))

function Demo() {
  const data = resource.read(666)
  return (
    <div>{data}</div>
  );
}
复制代码

细谈 Suspense

在上面的实例中,Suspense 组件传入了 fallback 属性,这个属性用于显示加载中的页面,就是俗称的 loading 咯。

那么我们在想一个问题,如果一个异步请求数据的过程非常快,这样会使得加载中画面一闪而过,导致闪屏。

Suspense 针对这种情况给出解决方案 maxDuration 属性:

<Suspense fallback={<Spinner />} maxDuration={500}>
  // ...
</Suspense>
复制代码

当异步获取数据的时间大于 maxDuration 时间时展示 fallback ,否则直接展示数据。

需要注意的是 maxDuration 属性只有在 Concurrent Mode 下才能生效,在以往的 Sync 模式下 maxDuration 始终为0, 具体使用简单给出一个实例:

// ReactDOM.render(<App />, document.getElementById('root'));
ReactDOM
  .unstable_createRoot(document.getElementById('root'))
  .render(
    <React.unstable_ConcurrentMode>
      <App />
    </React.unstable_ConcurrentMode>
  );
复制代码

原理

Suspense 的实现原理颇有争议。

当我们在 render 内写异步请求数据时会抛出一个异常,当然它应该是一个 promise ,这个异常会被 Suspense 内一个新的生命周期 ComponentDidCatch 捕获到,在这个生命周期内 Suspense 将子组件渲染为 loading ,等到异步请求结束,loading结束,此时又回到了正常的组件。

翻了一下 unstable_createResource 的源码,果然 Pending 状态下会 throw 一个 suspender 对象,这个对象就是一个 promise 。

function unstable_createResource(fetch, maybeHashInput) {
  // ...
  var resource = {
    read: function (input) {
      // ...
      var key = hashInput(input);
      var result = accessResult(resource, fetch, input, key);
      switch (result.status) {
        case Pending:
          {
            var suspender = result.value;
            throw suspender;
          }
        case Resolved:
          {
            var _value = result.value;
            return _value;
          }
        case Rejected:
          {
            var error = result.value;
            throw error;
          }
        default:
          // Should be unreachable
          return undefined;
      }
    },
    // ...
  };
  return resource;
}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

数学与泛型编程

数学与泛型编程

[美]亚历山大 A. 斯捷潘诺夫(Alexander A. Stepanov)、[美]丹尼尔 E. 罗斯(Daniel E. Rose) / 爱飞翔 / 机械工业出版社 / 2017-8 / 79

这是一本内容丰富而又通俗易懂的书籍,由优秀的软件设计师 Alexander A. Stepanov 与其同事 Daniel E. Rose 所撰写。作者在书中解释泛型编程的原则及其所依据的抽象数学概念,以帮助你写出简洁而强大的代码。 只要你对编程相当熟悉,并且擅长逻辑思考,那么就可以顺利阅读本书。Stepanov 与 Rose 会清晰地讲解相关的抽象代数及数论知识。他们首先解释数学家想要解决......一起来看看 《数学与泛型编程》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具