Created
January 25, 2016 04:02
-
-
Save tazsingh/2eb20c2c0ab8ecd3a365 to your computer and use it in GitHub Desktop.
incremental-redux-reducers example app (not tested)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {createStore, applyMiddleware, combineReducers} from "redux"; | |
import thunk from "redux-thunk"; | |
import {setupIncrementalReduxReducers, reducerStore} from "incremental-redux-reducers"; | |
// Create the store however you like. | |
// For example purposes, let's apply the thunk middleware. | |
const createStoreWithMiddleware = applyMiddleware( | |
thunk | |
)(createStore); | |
// And then let's create the rootStore with a noop reducer. | |
const rootStore = createStoreWithMiddleware(() => {}); | |
// This will add hooks to that rootStore that the lib will tap into. | |
setupIncrementalReduxReducers(rootStore); | |
// Alternatively, you can subscribe to the reducerStore and setup the rootStore as you like. | |
// As Dan Abramov mentioned, if you want to use Immutable everywhere or set up rootStore by hand, you can do that too. | |
// (Note this is an example, you probably wouldn't do this and the above line in a real app.) | |
reducerStore.subscribe(() => { | |
const reducerMapping = reducerStore.getState(); | |
// Do what you please with reducerMapping. | |
// This is what setupIncrementalReduxReducers is doing behind the scenes. | |
rootStore.replaceReducer(combineReducers(reducerMapping)); | |
}); | |
// Dan mentioned that storing the reducers in a Redux store and using Redux actions to communicate with it | |
// can be removed. I tried to conceptualize that but found myself implementing global state and communicating with it. | |
// Redux is my preferred way to communicate with global state. But happy to field recommendations that maintain | |
// enough flexibility for library consumers to do what they want (i.e. what I've demo'd with the subscribe hook here)! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Note this import is important to tell our bundler that this reducer is required by this component. | |
// That's how Webpack (for example) knows what to bundle for each chunk in our application. | |
// If multiple chunks require the same reducer, Webpack can then put it in a common chunk. | |
import usersReducer from "./usersReducer"; | |
import {mapReducersToProps} from "incremental-redux-reducers"; | |
import {connect} from "react-redux"; | |
// I've employed this mapReducersToProps function to make it easier to map the reducer function to the state tree | |
// since you've already had to require the reducer function here. May as well use its tagged name value! | |
@connect(mapReducersToProps({ | |
localUsers: usersReducer | |
})) | |
// Note that this is equivalent to writing: | |
// @connect((state) => { | |
// return { | |
// localUsers: state.users | |
// } | |
// }) | |
export default ({localUsers}) => { | |
// The usual component logic with your localUsers prop. | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {addReducer} from "incremental-redux-reducers"; | |
// addReducer will tell our reducerStore to assign the reducer function to the "users" key. | |
// Behind the scenes, this will dispatch a redux action as that's what the store responds to. | |
// addReducer will return the reducer function that's tagged with the name we assigned it. | |
export default addReducer("users", (state = [], action) => { | |
switch(action.type) { | |
// your usual reducer logic | |
default: | |
return state; | |
} | |
}); |
I also think it's important to have a library for this as hot module reloading is a bit tricky to implement in this context. I haven't gotten there yet but have been thinking of ways to implement it for a later version.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note that I prefer to define only the component as my code-split point and then let the component
import
what it needs for the chunk. This cleans up my codebase quite a bit as everything is consistent and I can write helper functions to DRY things up.This is opposed to using a
require.ensure
to load everything (i.e. component, reducers, styles, images etc.) as each code-split has different dependencies and therefore is difficult to unify through helper functions.