Code splitting / dynamically loading sagas
See original GitHub issueI just discovered redux-saga
and I am looking to start integrating this into my app. I am currently code splitting my reducers and using replaceReducer when they hit the correct route. From the saga examples it looks like they all use a rootSaga. The closest I found to an answer is https://github.com/yelouafi/redux-saga/issues/23#issuecomment-168762879 but I am not certain if this is the official API and usage.
My current setup looks something like this: http://stackoverflow.com/a/33045558 which I pasted a snippet below:
function createRoutes(reducerRegistry) {
return <Route path="/" component={App}>
<Route path="async" getComponent={(location, cb) => {
require.ensure([], require => {
reducerRegistry.register({async: require('./reducers/async')})
cb(null, require('./screens/Async'))
})
}}/>
</Route>
}
function createStore(reducerRegistry) {
var rootReducer = createReducer(reducerRegistry.getReducers())
var store = createStore(rootReducer)
reducerRegistry.setChangeListener((reducers) => {
store.replaceReducer(createReducer(reducers))
})
return store
}
From the other comment, it sounds like this should be possible, but it looks like sagas need access to the store?
<Route path="async" getComponent={(location, cb) => {
require.ensure([], require => {
reducerRegistry.register({async: require('./reducers/async').default})
const sagas = require('./sagas').default
// store?
runSaga(sagas)
// right api usage? where to get the store? does any array work?
sagas.forEach(saga => runSaga( saga(store.getState), store ))
// only supports one rootSaga, not an array?
runSaga( sagas(store.getState), store )
cb(null, require('./screens/Async'))
})
}}/>
It looks like a middleware approach was discussed in https://github.com/yelouafi/redux-saga/issues/13#issuecomment-168884656 that would have solved this, but it was closed. This could have potentially worked:
var store = createStore(rootReducer)
reducerRegistry.setChangeListener(reducers => {
store.replaceReducer(createReducer(reducers))
})
sagaRegistry.setChangeListener(iterator => {
store.runSaga(iterator)
})
Would this be the official usage? What about “stopping/removing/disconnecting” the sagas? Will this work with server side rendering?
Issue Analytics
- State:
- Created 8 years ago
- Comments:25 (11 by maintainers)
Top GitHub Comments
Hello there,
I had the same issue and found redux-injector for injecting reducers asynchronously via routing. I decided to create the same philosophy for redux-sagas : https://github.com/GuillaumeCisco/redux-sagas-injector
You can find an exemple in the README. Using
injectReducer
andinjectSaga
, you can easily load your js code asynchronously via routing and deciding what route need only what it needs.Hope you’ll enjoy it 🎉
PS: It also works with SSR Stream Caching and with react-redux >= 6.0.0
@johanneslumpe AFAIK you cannot hot-reload a saga. Changes to sagas during hot reloading should force an entire app refresh. What I do is pass in a “key” of the saga to a registry which calls
sagaMiddleware.run
. And I only run a saga when I register a saga with a key that is different from any key I’ve registered before. This is because the registration exists inside thegetComponent
call in a React Router<Route>
which is invoked on every route enter/change