zalmoxisus / redux-devtools-extension

Redux DevTools extension.
MIT License
13.5k stars 1.01k forks source link

[feature-request] Hot reloading actionCreators #279

Open alexstrat opened 7 years ago

alexstrat commented 7 years ago

An API to update the the action creators in redux-devtools when the action creators are replaced by HMR would be very useful.

Something like:

import actionCreators from './actionCreators';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
  actionCreators,
});

...

module.hot.accept('./actionCreators', () => {
  window.__REDUX_DEVTOOLS_EXTENSION__.updateActionCreators(require('./actionCreators'))
});
zalmoxisus commented 7 years ago

Thanks for the example!

The suggested method is similar to window.__REDUX_DEVTOOLS_EXTENSION__.updateStore, which we're deprecating, as being difficult to use for multiple stores (instances).

For recomputing reducers we're hooking into store.replaceReducer, but it's not perfect, as sometimes this method can be used outside of hot reloading. It would be great to include it as well.

Maybe something like:

import rootReducer from './reducers';
import actionCreators from './actionCreators';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
  actionCreators,
  hmr: hmr => {
    if (module.hot) {
      module.hot.accept('./reducers', () => {
        hmr.reducers(require('./reducers').default);
      });
      module.hot.accept('./actionCreators', () => {
        hmr.actionCreactors(require('./actionCreators').default);
      });
    }
 }
});
alexstrat commented 7 years ago

Woo ok, just realized how many ways redux-devtools-extension can be used (multiple store, with "no"-store, etc..) and thus understood why you suggested this API.

What about exposing a method to access Instance objects? Instance would hold methods etc. relative to management of an instance:

// in a single-instance context returns the instance, otherwise raise
const instance = window.__REDUX_DEVTOOLS_EXTENSION__.getInstance();

// get by instanceId
const instance = window.__REDUX_DEVTOOLS_EXTENSION__.getInstance(instanceId);

// get by store reference
const instance = window.__REDUX_DEVTOOLS_EXTENSION__.getInstance(store);

instance.updateActionCreators(actionCreators)
instance.updateStore(newStore)
instance.store.replaceReducer(reducer)

I prefer this OO approach to the functional one you suggested, but It's probably just a matter of style and taste.

zalmoxisus commented 7 years ago

Well, I'd also prefer an OO approach like:

const reduxDevtools = new window.__REDUX_DEVTOOLS_EXTENSION__CONSTRUCTOR({});

const store = createStore(reducer, preloadedState, reduxDevtools.compose(
    applyMiddleware(...middleware)
));

reduxDevtools.updateActionCreators(actionCreators);
reduxDevtools.updateStore(newStore)
// ...

though, IMO, the functional one would be easier to integrate and would avoid missing parts in production.