React Hooks + Suspense を試す

react

これまで、React で非同期処理(データを取ってきて、取れたら表示を更新する等)をするには、大変な苦労を伴いました。

Reduxのmiddlewareを駆使したり、Hooks、redux-saga、useEffect等をこねくりまわしてなんとかしていました。

しかし、これからは React 公式の機能 Suspense を使うことで、非同期処理を React らしく記述することができます。

そこでReactが行き着いたひとつの答えがSuspenseです。Suspenseは非同期処理を無理やりReactの世界に引きずり込み、Reactの流儀で制御できるようになります。

詳細は以下の記事に書かれています。

ReactのSuspenseで非同期処理を乗りこなす – 2020年2月10日
https://sbfl.net/blog/2020/02/10/react-suspense-async

上記の内容を Create React App で動かしてみました。
(React 17.0.2, Create React App 4.0.3 で動作することを確認済み)

Create React App
https://create-react-app.dev

Create React App で動かす手順

Apple Silicon macOS Big Sur で動作確認済み。

プロジェクトの作成

% npx create-react-app my-react --template typescript

src/App.tsx を以下のように書き換えます。

import React, { Suspense } from 'react';

const wrapPromise = (promise: any) => {
  let status = 'pending';
  let result: any;

  const suspender = promise.then(
    (r: any) => {
      status = 'fulfilled';
      result = r;
    },
    (e: any) => {
      status = 'rejected';
      result = e;
  });

  const read = () => {
    if(status === 'pending') {
      throw suspender;
    } else if(status === 'rejected') {
      throw result;
    } else {
      return result;
    }
  };

  return { read };
}

const fetchTodoList = () => {
  const promise = new Promise((resolve, reject) => {
    setTimeout(()=> {
      resolve([
        'Reactの復習',
        'Error Boundaryについて知る',
        'Suspenseについて勉強する'
      ]);
    }, 1000);
  });

  return wrapPromise(promise);
};

const todoListResource = fetchTodoList();

const TodoList = () => {
  // ここでデータが読み込めているかどうかは気にしなくて良い
  const todoList = todoListResource.read();

  // 読み込めている前提でコードを書ける
  const items = todoList.map((todo: any) => <li>{todo}</li>);
  return <ul>{items}</ul>;
};

export const App = () => {
  // データが読み込めていない場合はSuspenseが面倒を見る
  // ここでは「Loading...」と表示する
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <TodoList/>
    </Suspense>
  )
};

export default App;

フォルダを移動

% cd my-react

Create React App を起動

% npm start

ブラウザで localhost:3000 にアクセスし
以下の表示がでれば成功です。

コメント

タイトルとURLをコピーしました