これまで、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 にアクセスし
以下の表示がでれば成功です。
コメント