Skip to content

Instantly share code, notes, and snippets.

@Grokling
Created June 30, 2016 11:24
Show Gist options
  • Save Grokling/fed9360a7951d5e337194aed00f823ba to your computer and use it in GitHub Desktop.
Save Grokling/fed9360a7951d5e337194aed00f823ba to your computer and use it in GitHub Desktop.
Additions to jpsierens boilerplate for hot reloading of sagas and reducers
/**
* Combine all reducers in this file and export the combined reducers.
* If we were to do this in store.js, reducers wouldn't be hot reloadable.
*/
import { combineReducers } from 'redux';
import { LOCATION_CHANGE } from 'react-router-redux';
/*
* routeReducer
*
* The reducer merges route location changes into our immutable state.
* The change is necessitated by moving to react-router-redux@4
*
*/
// Initial routing state
const routeInitialState = {
locationBeforeTransitions: null,
};
/**
* Merge route into the global application state
*/
function routeReducer(state = routeInitialState, action) {
switch (action.type) {
/* istanbul ignore next */
case LOCATION_CHANGE:
return {...state, locationBeforeTransitions: action.payload}
default:
return state;
}
}
import { reducer as auth } from 'redux/modules/auth';
import { reducer as clock } from 'redux/modules/clock';
import { reducer as order } from 'redux/modules/order';
import { reducer as suppliers } from 'redux/modules/suppliers';
export default function () {
return combineReducers({
route: routeReducer,
auth: auth,
clock: clock,
order: order,
suppliers: suppliers,
})
};
import { take, fork, cancel } from 'redux-saga/effects';
export const CANCEL_SAGAS_HMR = 'CANCEL_SAGAS_HMR';
import auth from 'redux/sagas/auth';
import order from 'redux/sagas/order';
import clock from 'redux/sagas/clock';
function createAbortableSaga (saga) {
// console.log('saga', saga);
if (__isDev__) {
return function* main () {
const sagaTask = yield fork(saga);
yield take(CANCEL_SAGAS_HMR);
yield cancel(sagaTask);
};
} else {
return saga;
}
}
const allSagas = [...auth, ...order, ...clock];
const SagaManager = {
startSagas(sagaMiddleware) {
allSagas
.map(createAbortableSaga)
.forEach((abortableSaga) => {
sagaMiddleware.run(abortableSaga);
});
},
cancelSagas(store) {
store.dispatch({
type: CANCEL_SAGAS_HMR
});
}
};
export default SagaManager;
// Adapted from https://gist.github.com/hoschi/6538249ad079116840825e20c48f1690
import { applyMiddleware, createStore, compose } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { routerMiddleware } from 'react-router-redux';
import rootReducer from './rootReducer';
import sagaManager from './sagaManager';
// let devTools;
// if (process.env.NODE_ENV === 'development' && window.devToolsExtension) {
// devtools = window.devToolsExtension
// } else devTools = (() => noop => noop);
const devTools = window.devToolsExtension || (() => noop => noop);
export default function configureStore (initialState = {}, history) {
const sagaMiddleware = createSagaMiddleware();
const middlewares = [
sagaMiddleware,
routerMiddleware(history),
];
const enhancers = [
applyMiddleware(...middlewares),
devTools(),
];
let middleware = applyMiddleware(sagaMiddleware);
const store = createStore(
rootReducer(),
initialState,
compose(...enhancers)
);
sagaManager.startSagas(sagaMiddleware);
if (module.hot) {
// enable hot module reloading for reducers
module.hot.accept('./rootReducer', () => {
require('./rootReducer').default()
.then((nextReducer) =>{
console.log('Reducers got updated');
store.replaceReducer(nextReducer);
})
});
// enable hot module reloading for sagas
module.hot.accept('./sagaManager', () => {
console.log('Sagas got updated');
sagaManager.cancelSagas(store);
require('./sagaManager').default.startSagas(sagaMiddleware);
});
}
return store;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment