This function create a saga that runs the sagas in the startingSagas
array and takes
the actions with type indicated by changeActionType
to replace the running sagas.
The replacing actions must have a field sagas
cointaining the array with the new sagas.
function createDynamicSaga (changeActionType, startingSagas) {
function* _start (sagas) {
try {
yield sagas
} catch (e) {
console.error('error', e)
}
}
return function* dynamicSaga () {
let action
let rootTask = yield fork(_start, startingSagas)
while (action = yield take(changeActionType)) {
yield cancel(rootTask)
rootTask = yield fork(_start, action.sagas)
}
}
}
How to use:
const rootSagas = [
// ... my sagas
]
const sagaMiddleware = createSagaMiddleware()
const store = createStore(myReducers, INITIAL_STATE, applyMiddleware(sagaMiddleware))
sagaMiddleware.run(createDynamicSaga('SET_SAGAS', rootSagas))
// ...
// replace sagas
store.dispatch({ type: 'SET_SAGAS', sagas: [ /* ... new sagas */ ] })
The example shows how to create a root dynamic saga but this is function can also be used to create dynamic sub sagas to have some fixed sagas and some replaceable sagas.
When replacing sagas, do not reuse generator objects from previous running sagas. If you want to reuse old sagas you have to recreate them.
Wrong:
const reusedSaga = [
takeEvery(SOME_ACTION, someActionSaga)
]
// ...
store.dispatch({ type: 'SET_SAGAS', sagas: [
...reusedSaga,
// some other new sagas
]})
Change to:
const getReusedSaga = () => [
takeEvery(SOME_ACTION, someActionSaga)
]
// ...
store.dispatch({ type: 'SET_SAGAS', sagas: [
...getReusedSaga(),
// some other new sagas
]})