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



コメント