React.SuspenseとsetTimeoutで最小限の非同期コンポーネントをつくる

Nov 5, 2020 15:07 · 440 words · 1 minute read

こんなコードで1秒後に helloworld と表示できるコンポーネントが作れる

// 「1秒以内はPromiseがthrowされて、1秒後にはundefinedが返ってくる関数」を返す関数
const delay = () => {
  let isTimeout = false;
  // 1秒後にisTimeoutがTrueになる
  const promise = new Promise(resolve => setTimeout(() => resolve(), 1000));
  promise.then(() => (isTimeout = true));

  return () => {
    if (isTimeout) {
      return;
    } else {
      // 1秒まではいつ呼んでもPromiseがthrowされる
      // Promiseがthrowされる限りSuspenseはfallbackを表示する
      throw promise;
    }
  };
};
let f;
const Trigger = () => {
  // このあと何回Trigger関数が呼ばれても1秒間はPromiseがthrowされる
  f = f || delay();
  f();
  // 1秒後からTrigger関数は正常に終了して普通のコンポーネントが返ってくるようになる
  return <p>hello world</p>;
};
const DelayedComp = () => {
  return (
    // throwされたPromiseはReact.Suspenseがcatchしてfallbackを表示してくれる
    <React.Suspense fallback={<p>loading...</p>}>
      <Trigger />
    </React.Suspense>
  );
};
ReactDOMServer.renderToString(<DelayedComp />);

参考

tweet Share