Closed emilchacko closed 9 years ago
There's a discussion going on about this over on redux-devtools#24 and I've been working on it (unsuccessfully) on the reducer-reload-test branch. Any testing or debugging time you could put into it would be appreciated.
I haven't gone back to work on this. It doesn't affect me that much. It should be pretty easy to suss out for @gaearon, but he's so busy with the 1.0 docs.
Ping me in a week or so?
Will do. I just had a head scratching moment caused by my reducer not hot reloading, so I retract my previous "this doesn't affect me" statement. :smile:
:speaker: Ping!
So, the issue is with where the store is created, right? Why not create the store within the router file, rather than passing it in? You would pass in the initial state, not a fully composed store object, as the 3rd parameter.
If you need the store back outside of the router (which it looks like you do for the dev tools and SSR), include it in the resolve()
.
Based on todomvc example in redux-devtools I figured out that Hotloading for reducers stop working after we just add this line import * as reducers from './reducers';
to index.js file.
Unfortunately it's not so easy. As @gaearon said, file that create store must:
Just moving store creation logic won't help - we still exporting Promise, not the root React component
Yeah, there is problem to create stores inside the Root React component, when we are using react-router, for example.
More over for my App, that was created from scratch, I implemented all 3 points from @gaearon, but it didn't help. So I'll wait for docs with universal react-router
@gaearon pinging again! :p any chance you can give us a hand here?
Which branch should I try?
As I said, just add this line import * as reducers from './reducers';
to index.js file in your todomvc example in redux-devtools, and reducers hot reloading stop working. And need to reload server after that
@gaearon This is the branch where I tried to get it working, but you could start fresh from master
, too.
@erikras Getting this on master
:
ROUTER ERROR: TypeError: Cannot convert undefined or null to object
- Function.keys
- Html.js:40 Html.render
/Users/dan/p/react-redux-universal-hot-example/src/Html.js:40:19
- ReactCompositeComponent.js:789 [object Object].ReactCompositeComponentMixin. _renderValidatedComponentWithoutOwnerOrContext
[react-redux-universal-hot-example]/[react]/lib/ReactCompositeComponent.js:7 89:34
As I said, just add this line import * as reducers from './reducers'; to index.js file in your todomvc example in redux-devtools, and reducers hot reloading stop working.
That's the expected behavior. :-)
@gaearon Very strange. I just blew away my webpack-stats.json
, node_modules
, ran npm install
, and master
is working for me with npm run dev
.
Eh, I ran npm start
. :-P Yeah I can run it now. Will investigate.
The simplest fix is to use Webpack's HMR API directly:
/* global __DEVELOPMENT__, __CLIENT__, __DEVTOOLS__ */
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import createMiddleware from './clientMiddleware';
import * as reducers from '../reducers/index';
let reducer = combineReducers(reducers);
let lastCreatedStore; // <------------------------------- remember store
if (module.hot) {
module.hot.accept('../reducers/index', () => {
reducer = combineReducers(require('../reducers/index'));
lastCreatedStore.replaceReducer(reducer);
});
}
export default function(client, data) {
const middleware = createMiddleware(client);
let finalCreateStore;
if (__DEVELOPMENT__ && __CLIENT__ && __DEVTOOLS__) {
const { devTools, persistState } = require('redux-devtools');
finalCreateStore = compose(
applyMiddleware(middleware),
devTools(),
persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)),
createStore
);
} else {
finalCreateStore = applyMiddleware(middleware)(createStore);
}
const store = finalCreateStore(reducer, data);
store.client = client;
lastCreatedStore = store; // <------------------ remember store
return store;
}
We'll have a better fix later, but you can use this for now.
Awesome, @gaearon!!! I knew it'd be a matter of minutes for you. :smile:
Work like a charm, huge thanks!
Simpler way to write the same thing:
/* global __DEVELOPMENT__, __CLIENT__, __DEVTOOLS__ */
import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import createMiddleware from './clientMiddleware';
export default function(client, data) {
const middleware = createMiddleware(client);
let finalCreateStore;
if (__DEVELOPMENT__ && __CLIENT__ && __DEVTOOLS__) {
const { devTools, persistState } = require('redux-devtools');
finalCreateStore = compose(
applyMiddleware(middleware),
devTools(),
persistState(window.location.href.match(/[?&]debug_session=([^&]+)\b/)),
createStore
);
} else {
finalCreateStore = applyMiddleware(middleware)(createStore);
}
const reducer = combineReducers(require('../reducers/index'));
const store = finalCreateStore(reducer, data);
store.client = client;
if (module.hot) {
module.hot.accept('../reducers/index', () => {
const nextReducer = combineReducers(require('../reducers/index'));
store.replaceReducer(nextReducer);
});
}
return store;
}
Note that module.hot.accept
is mutative and calling it many times replaces the hot update handler. This means that hot replacement will only work for the store you create()
last. But in Redux you should have one store anyway, so not a problem.
@gaearon @erikras thank you guys
No problem, sorry it took me so long to come back to this.
case COUNTER_INCREMENT: let {count} = state; return { count: count +1 };
changed it to
case COUNTER_INCREMENT: let {count} = state; return { count: count +10 };
I'm getting the console log as:
[1] [piping] File src/reducers/counter.js has changed, reloading. [0] Hash: 9bc9239a8a2f86a42fe5 [0] Version: webpack 1.10.3 [0] Time: 215ms [0] Asset Size Chunks Chunk Names [0] main-9bc9239a8a2f86a42fe5.js 3.02 MB 0 [emitted] main [0] 0.4416de2fe6fb28b0fffb.hot-update.js 3.02 kB 0 [emitted] main [0] 4416de2fe6fb28b0fffb.hot-update.json 36 bytes [emitted]
but it doesn't get reflected when I try to increment it using the button .What am I missing ?