在React18中,配合Suspense来获取数据

在React18的版本中,<Suspense>组件可以用于数据获取。
首先,要实现一个数据的加载器:
interface WrapPromise<T> {
  read(): T | undefined;
}

enum WrapStatus {
  Pending = 'pending',
  Success = 'success',
  Error = 'error'
}

/**
 * 加载器
 * @param { () => Promise<T> } promise: 一个返回Promise的函数
 */
function wrapPromise<T = unknown>(promise: () => Promise<T>): WrapPromise<T> {
  let status: WrapStatus = WrapStatus.Pending;
  let result: T | Error;
  let suspender: Promise<void>;

  // 第一次读取read时运行promise
  function runPromise(): void {
    suspender ??= promise().then<void, void>(
      (value: T): void => {
        status = WrapStatus.Success;
        result = value;
      },
      (err: Error): void => {
        status = WrapStatus.Error;
        result = err;
      }
    );
  }

  return {
    read(): T | undefined {
      runPromise();

      if (status === WrapStatus.Pending) {
        throw suspender;
      } else if (status === WrapStatus.Error) {
        throw result;
      } else if (status === WrapStatus.Success) {
        return result as T;
      }
    }
  };
}
然后在组件内调用:
import { Suspense } from 'react';

const g = wrapPromise(getData);

function Child(props) {
  const data = g.read();

  return <div>{ data }</div>;
}

function Demo(props) {
  return (
    <Suspense fallback="Loading...">
      <Child />
    </Suspense>
  );
}