-
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.
// ------------ | |
// 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! |
I understand what you're suggesting but I'm sure it's going to be a pain in a large app to keep inventing keys so they don't clash, and it will look exactly the same namespaced way in the end.
I think that the problem of components tied to particular state keys is better solved by composing their select
methods. This is exactly what NuclearJS does with "getters". It's already possible in Redux but not really documented yet. Here's some info:
@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
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.
Hi,
I like your idea of redux and composing stores but I see the same problem as @alexeyraspopov mentioned regarding combininig independent stores. The reason is, that the container component must know the composition hierarchy. Therefore previously independent store/component combinations would be coupled with other stores.
Therefore I would propose to provide an alternative way to combine stores in a flat way.
The combining function would look like this:
The composeStoresFlat would like like this:
The initialization of redux would be done in the following way:
Finally the component needing the counter information can select the counter independent of the todos and vice versa. Hence it allows to reuse stores and corresponding container components independent of their composition: