Posted by
Mike Wolf
React Hot Module Reloading
I'm thinking of getting back into doing some coding. If I do, I'll need to recover some technology that I once knew. Here are some tidbits to not get lost.
WebPack Hot Module Reloading
From here
And here's a problem with Redux (not copied)
And it looks like ReactHotLoader now does the right stuff, including living peacefully inside create-react-app
WebPack Hot Module Reloading
From here
And here's a problem with Redux (not copied)
And it looks like ReactHotLoader now does the right stuff, including living peacefully inside create-react-app
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import configureStore from "./store/configureStore"; | |
const store = configureStore(); | |
const rootEl = document.getElementById("root"); | |
let render = () => { | |
const RootAppComponent = require("containers/RootAppComponent").default; | |
ReactDOM.render( | |
<RootAppComponent store={store} />, | |
rootEl | |
); | |
}; | |
if(module.hot) { | |
// Support hot reloading of components | |
// and display an overlay for runtime errors | |
const renderApp = render; | |
const renderError = (error) => { | |
const RedBox = require("redbox-react"); | |
ReactDOM.render( | |
<RedBox error={error} />, | |
rootEl, | |
); | |
}; | |
render = () => { | |
try { | |
renderApp(); | |
} | |
catch(error) { | |
renderError(error); | |
} | |
}; | |
module.hot.accept("./containers/Root", () => { | |
setTimeout(render); | |
}); | |
} | |
render(); |
import {createStore, applyMiddleware, compose} from "redux"; | |
import rootReducer from "../reducers/rootReducer"; | |
import thunk from "redux-thunk"; | |
import createSagaMiddleware from 'redux-saga'; | |
import SagaManager from "sagas/SagaManager"; | |
/** | |
* Based on the current environment variable, we need to make sure | |
* to exclude any DevTools-related code from the production builds. | |
* The code is envify'd - using 'DefinePlugin' in Webpack. | |
*/ | |
const sagaMiddleware = createSagaMiddleware(); | |
const middlewares = [thunk, sagaMiddleware]; | |
const storeEnhancers = []; | |
if(__DEV__) { | |
const DevTools = require("../containers/DevTools").default; | |
// If the user has the "Redux DevTools" browser extension installed, use that. | |
// Otherwise, hook up the in-page DevTools UI component. | |
const debugEnhancer = window.devToolsExtension ? window.devToolsExtension() : DevTools.instrument(); | |
storeEnhancers.push(debugEnhancer); | |
} | |
const middlewareEnhancer = applyMiddleware(...middlewares); | |
storeEnhancers.unshift(middlewareEnhancer); | |
export default function configureStore(initialState) { | |
const store = createStore( | |
rootReducer, | |
initialState, | |
compose(...storeEnhancers) | |
); | |
// run sagas | |
SagaManager.startSagas(sagaMiddleware); | |
if(__DEV__) { | |
// Hot reload reducers (requires Webpack or Browserify HMR to be enabled) | |
if(module.hot) { | |
module.hot.accept("../reducers/rootReducer", () => | |
store.replaceReducer(require("../reducers/rootReducer").default) | |
); | |
module.hot.accept('../sagas/SagaManager', () => { | |
SagaManager.cancelSagas(store); | |
require('../sagas/SagaManager').default.startSagas(sagaMiddleware); | |
}); | |
} | |
} | |
return store; | |
} |
// Borrowed from https://gist.github.com/hoschi/6538249ad079116840825e20c48f1690 | |
// Note that reloading sagas has several issues/caveats to be aware of. | |
// See https://github.com/yelouafi/redux-saga/issues/22#issuecomment-218737951 for discussion. | |
import { take, fork, cancel } from 'redux-saga/effects'; | |
import rootSaga from "./rootSaga"; | |
const sagas = [rootSaga]; | |
export const CANCEL_SAGAS_HMR = 'CANCEL_SAGAS_HMR'; | |
function createAbortableSaga (saga) { | |
if (process.env.NODE_ENV === 'development') { | |
return function* main () { | |
const sagaTask = yield fork(saga); | |
yield take(CANCEL_SAGAS_HMR); | |
yield cancel(sagaTask); | |
}; | |
} else { | |
return saga; | |
} | |
} | |
const SagaManager = { | |
startSagas(sagaMiddleware) { | |
sagas.map(createAbortableSaga).forEach((saga) => sagaMiddleware.run(saga)); | |
}, | |
cancelSagas(store) { | |
store.dispatch({ | |
type: CANCEL_SAGAS_HMR | |
}); | |
} | |
}; | |
export default SagaManager; |
Comments
Post a Comment