Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux Saga hot reloading

Tags:

I was working on a React & Redux project. The project used to use webpack-dev-middleware and hot middleware to hot reload.

After I added Redux Saga to the project, and added saga middleware to the redux store. It seems that whenever I change the saga codes, the hot reloading will broke and display an error message:

Provider> does not support changing store on the fly. It is most likely that you see this error because you updated to Redux 2.x and React Redux 2.x which no longer hot reload reducers automatically. See https://github.com/reactjs/react-redux/releases/tag/v2.0.0 for the migration instructions.

I understand that Saga uses generators and it is time dependent. Is it possible to hot reload the page with Sagas? just like how Redux reducers replace itself during hot reloading.

Thanks!

like image 578
Kevin He Avatar asked May 10 '16 20:05

Kevin He


People also ask

What is hot reloading in Redux?

Hot module replacement is one of the most useful features offered by Webpack. It allows all kinds of modules, including JSON, CSS, and JS files, to be updated at runtime without needing a full refresh.

Is Redux saga overkill?

Once you start using one of these libraries, you will find that on the vast majority of projects, Redux is overkill. When the data fetching/caching part of your app is taken care of, there is very little global state for you to handle on the frontend.

Is Redux saga obsolete?

Such a powerful & elegant tool as Redux-Saga, a Redux side effect manager, is said to be deprecated, and no longer being maintained, starting from Jan 27, 2021.

What is hot module reloading?

Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running, without a full reload. This can significantly speed up development in a few ways: Retain application state which is lost during a full reload.


1 Answers

I'm working on a project with redux and redux-saga (but not react). I implemented the hot reloading of sagas using the sagaMiddleware.run() but you have to handle the module reloading and replace reducers and sagas as indicated in the link you provided (https://github.com/reactjs/react-redux/releases/tag/v2.0.0).

import { createStore } from 'redux'; import rootReducer from '../reducers/index'; import getSagas from '../sagas';  export default function configureStore(initialState) {   const sagaMiddleware = createSagaMiddleware()   const store = createStore(rootReducer, initialState, applyMiddleware(sagaMiddleware));   let sagaTask = sagaMiddleware.run(function* () {      yield getSagas()   })   if (module.hot) {     // Enable Webpack hot module replacement for reducers     module.hot.accept('../reducers', () => {       const nextRootReducer = require('../reducers/index');       store.replaceReducer(nextRootReducer);     });     module.hot.accept('../sagas', () => {       const getNewSagas = require('../sagas');       sagaTask.cancel()       sagaTask.done.then(() => {         sagaTask = sagaMiddleware.run(function* replacedSaga (action) {           yield getNewSagas()         })       })     })   }    return store; } 

An important thing to notice is the getSagas() function. It returns an array of freshly created generator object of sagas, you cannot have some precreated object in the array from some already running sagas. If you buid this array only in one module, you can use directly a constant array, but if you build it composing sagas from different modules you have to be sure to recreate sagas from all modules, so the better way is that all modules export creating function instead of exporting a fixed saga or array of sagas. For example it could be a function like this:

export default () => [   takeEvery(SOME_ACTION, someActionSaga),   takeEvery(OTHER_ACTION, otherActionSaga), ] 

Obviously all sagas are restarted from beginning and if you have a complex sagas with internal state you lose the current state.

A very similar approach is to use a dynamic saga in place of calling sagaMidleware.run(), it a very similar solution but you can reload subsets of the sagas and handle them in different ways. For more info see https://gist.github.com/mpolci/f44635dc761955730f8479b271151cf2

like image 125
mpolci Avatar answered Oct 22 '22 02:10

mpolci