redux-sagaでtakeEveryをcancelする
takeEveryで動かしている処理をcancelしたい場合、raceを使って停止させます。 これは、raceで何もしない処理と同時実行することで、「何もしない処理が先に完了したので、処理を完了とする」判定を出すやり方で […]
広告ここから
広告ここまで
目次
takeEvery
で動かしている処理をcancelしたい場合、race
を使って停止させます。
/**
* Actions
**/
const START = 'START' as const
const CANCEL = 'CANCEL' as const
const start = () => ({
type: START,
})
const cancel = () => ({
type: CANCEL
})
function* startSaga() {
// Do something
}
function* exampleSaga() {
yield takeEvery([START], function*(...args) {
yield race({
task: call(startSaga, ...args),
cancel: take(CANCEL)
})
}
}
これは、race
で何もしない処理と同時実行することで、「何もしない処理が先に完了したので、処理を完了とする」判定を出すやり方で、Automatic cancellation
としてドキュメントにも紹介されています。
In a
race
effect. All race competitors, except the winner, are automatically cancelled.https://redux-saga.js.org/docs/advanced/TaskCancellation/#automatic-cancellation
ラッパー関数を作るなら
頻繁にCancelの必要があるtakeEvery
を書く場合は、以下のようなラッパーを用意しておくと便利です。
import { takeEvery, call, race, take } from 'redux-saga/effects';
/**
* Cancelable takeEvery
* @example
* ```
* yield takeEveryWithCancel({
* actionNames: 'START',
* callback: taskSaga
* }, 'STOP')
* ```
*/
function* takeEveryWithCancel(task: {
actionNames: string | string[];
callback: (...args) => void
}, cancelActionName: string) {
yield takeEvery(
task.actionNames,
function* (...args) {
yield race({
task: call(task.callback, ...args),
cancel: take(cancelActionName),
});
}
);
}
使う時はこんな感じで書きます。
yield takeEveryWithCancel({
actionNames: START,
callback: startSaga
}, STOP)