やりたいこと
redux-saga の call を行う際に
レスポンスを待っている間はロード中をオーバーレイで表示をさせたい!
画像は material ui の circular
https://material-ui.com/components/progress/#circular
問題点
◇saga 全体を監視していずれかのタスクが call中 であるという判定を行いたい
◇しかし、既存の sagaのソースや fetch(axios)部分にまで侵入したくない
◇saga の記述をする際に、必要なコード量を増やしたくない
既存の記事等を検索するも、これらを満たしてくれる方法が見つからない・・・
解決策
海外サイトでも見当たらないので、公式ドキュメントを血眼になって読み漁ると
https://redux-saga.js.org/docs/api/
sagaMonitor なるものがあるらしい
説明を読んだが、sampleが記述されておらず、アホの僕には具体的な実装がよくわからない
ライブラリの中を見に行って、sagaMonitor を使用している場所を見つけた
https://github.com/redux-saga/redux-saga/blob/a79e2cda8530930c172d1ffb53027adb7443e879/examples/real-world/store/configureStore.prod.js
この @redux-saga/simple-saga-monitor というライブラリを見てみると
どうやら saga のロガーとして使用しているらしい
発火した effect や 解決した effect を検知できるようだ
という訳でこの sagaMonitor を使用して実装していく
sagaMonitor
何はともあれ、とりあえずコード
省略
.
.
.
import createSagaMiddleware from 'redux-saga'
import {setEffect, deleteEffect} from './actions/sagaMonitor'
import rootSaga from './sagas'
// 対象のコードはここから
const watchEffectEnd = (effectId, res) => {
store.dispatch(deleteEffect(effectId))
};
const sagaMonitor = {
effectRejected: (e) => {
store.dispatch(deleteEffect(e.effectId))
},
effectTriggered: (event) => {
if (event.effect.type === 'CALL') {
store.dispatch(setEffect(event.effectId))
}
},
effectResolved: watchEffectEnd,
}
// 対象のコードはここまで
export const history = createBrowserHistory()
const sagaMiddleware = createSagaMiddleware({sagaMonitor: sagaMonitor})
省略
.
.
.
let store = null;
export default function configureStore(preloadedState) {
store = createStore(
createRootReducer(history),
preloadedState,
bindMiddleware()
);
sagaMiddleware.run(rootSaga);
return store;
}
そんなに解説するところは無いが
createSagaMiddleware()の引数に、作成したsagaMonitorオブジェクトを渡せばいいだけ
effectTriggered で、発火したタスク名やメソッド名がid付きで取得できる
effectResolved で、解決したタスク名等が発火時に付与されたid付きで取得できる
これで reducer に発火時にidを詰め、解決時にidを削除するという事が可能になる
あとはコンポーネント側で、reducer に何か詰まっている状態 の時はローダーを表示させれば良い
effectRejected とか他にもメソッドがあるけど、その辺はよしなにお願いします
最後に
sagaMonitor がこういう使い方しても良いのかはわかりません