Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Do not merge!) Discussion: A userland replacement for replaceReducer #625

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 0 additions & 16 deletions examples/counter/containers/Root.js

This file was deleted.

12 changes: 9 additions & 3 deletions examples/counter/index.js
@@ -1,7 +1,13 @@
import React from 'react';
import Root from './containers/Root';
import { Provider } from 'react-redux';
import CounterApp from './containers/CounterApp';
import configureStore from './store/configureStore';

const store = configureStore();

React.render(
<Root />,
<Provider store={store}>
{() => <CounterApp />}
</Provider>,
document.getElementById('root')
);
)
22 changes: 16 additions & 6 deletions examples/counter/store/configureStore.js
@@ -1,11 +1,21 @@
import { createStore, applyMiddleware } from 'redux';
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from '../reducers';
import reducer from '../reducers';
import switchReducer from './switchReducer';

const createStoreWithMiddleware = applyMiddleware(
thunk
)(createStore);
function onHotReload(useReducer) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the param for onHotReload() be the path to the reducer module? Or does that not work because the require statement can't be inside node_modules?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand what you're proposing.

The problem is Webpack needs module.hot.accept(name call to be verbatim and statically analyzable (also true for require call inside).

Also, switchReducer argument isn't specific to hot reloading. It's just a function that invokes a callback whenever there's a new reducer available. This can be a result of hot reloading, code splitting, or even both.

module.hot.accept('../reducers', () => {
const nextReducer = require('../reducers');
useReducer(nextReducer);
});
}

const finalCreateStore = compose(
switchReducer(onHotReload),
applyMiddleware(thunk),
createStore
);

export default function configureStore(initialState) {
return createStoreWithMiddleware(rootReducer, initialState);
return finalCreateStore(reducer, initialState);
}
19 changes: 19 additions & 0 deletions examples/counter/store/switchReducer.js
@@ -0,0 +1,19 @@
// Note: this is meant to be provided in a separate package.
// I'm only including it here for discussion.

const SWITCH_REDUCER = { type: 'redux-switch/SWITCH_REDUCER' };
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason you've left off the @@ at the beginning?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving the @@ may be because this is intended to be implemented in userland.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I interpreted "userland" to mean another npm package, a la redux-thunk et al.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, forgot about it. Yeah, it's probably better to leave it in because I can't imagine a siutation where you'd want to handle it.


export default function switchReducer(onNextReducer) {
return next => (reducer, initialState) => {
let currentReducer = reducer;
let switchingReducer = (state, action) => currentReducer(state, action);
let store = next(switchingReducer, initialState);

onNextReducer(nextReducer => {
currentReducer = nextReducer;
store.dispatch({ type: SWITCH_REDUCER });
});

return store;
};
}