Skip to content

Instantly share code, notes, and snippets.

@gaearon
Created June 3, 2015 18:03
Show Gist options
  • Star 123 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save gaearon/d77ca812015c0356654f to your computer and use it in GitHub Desktop.
Save gaearon/d77ca812015c0356654f to your computer and use it in GitHub Desktop.
Combining Stateless Stores
// ------------
// counterStore.js
// ------------
import {
INCREMENT_COUNTER,
DECREMENT_COUNTER
} from '../constants/ActionTypes';
const initialState = { counter: 0 };
function increment({ counter }) {
return { counter: counter + 1 };
}
function decrement({ counter }) {
return { counter: counter - 1 };
}
export default function counterStore(state = initialState, action) {
switch (action.type) {
case INCREMENT_COUNTER:
return increment(state, action);
case DECREMENT_COUNTER:
return decrement(state, action);
default:
return state;
}
}
// ------------
// todoStore.js
// ------------
import { ADD_TODO } from '../constants/ActionTypes';
const initialState = {
todos: [{
text: 'do something',
id: 0
}]
};
export default function todoStore(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return {
todos: [{
id: state.todos[0].id + 1,
text: action.text
}].concat(state.todos)
};
}
return state;
}
// ------------
// combinedStore.js
// ------------
// Let's say at some point I know that these stores depend on each other in some way.
// If I *decide* I want to hide these stores as impl details of a single store
// I don't need to change their public APIs at all. I just register combinedStore instead.
import counterStore from './counterStore';
import todoStore from '../todoStore';
const initialState = {
counterData: undefined,
todoData: undefined
};
export default function combinedStore(state = initialState, action) {
const counterData = counterStore(state.counterData, action);
const todoData = todoStore(state.todoData, action);
return { counterData, todoData };
}
// So it's trivial to "merge" stores but keep the delegation. This is exactly how Elm models work too.
// Now, if I *want* to, I can make substores more custom (e.g. make a store factory that responds only to
// actions matching predicate, like createFollowersStore(userId) => FollowersStore that responds to specific
// userId in the action). Composition all the way!
@quirinpa
Copy link

@fisherwebdev I just published a small middleware that i think can help you solve that problem: redux-next I hope it helps but it doesn't quite react to the store though... :P

Here are a cople of other middlewares i made redux-delay and redux-client-next (middleware creator function) lol @ my useless contributions

@goldensunliu
Copy link

I can see the benefit of combined store that rules them all so stores don't have to talk/depend on each other, however i.e the combined store now owns the dependency as one abstraction level up, this is more likely to be more readable and easier to manage as an application grows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment