Local Store redux, (multiple stores)
dam0vm3nt opened this issue · 6 comments
What do you think about defining a new mixin, beside the current one, that will create a new store for each element ?
This would be usefull to implement a pattern of store and sub-store. What I'm trying to accomplish is a pattern where a store can have children store to manage a sub set of the data. Changes between the parent and the child are propagated via polymer binding (parent -> child) and events (child -> parent).
For example in a todo list app, when I add a new todo renderer whith its own sub-store is created. via property biding and observers an actionis dispatched in the sub-store to initialize its state. When the todo is edited in the renderer an event is fired upwards in order to update the main app store.
In my honest opinion I think it's a little too complicated, maybe over engineered. The idea of Redux itself is to have a single store. If you wish for components/elements to have subsets of the store's data then I highly recommend you use reselect for your statePath
.
Using reselect
import {createSelector} from 'reselect';
// we select the state.todos list using the state.key
const selectTodoList = state => state.todos[state.key];
// create the selector for the property's statePath
const todoListSelector = createSelector(selectTodoList);
class App extends ReduxMixin(Polymer.Element) {
static get properties() {
return {
todoList: {
// use the selector as the statePath
statePath: todoListSelector
}
};
}
switchTodoList(key) {
// switch to a todo list "subset" data from the single store
// this will change the value of this.todoList property via the selector
this.dispatch({
type: 'CHANGE_TODO_KEY',
key
});
}
}
Redux is a very simple concept and having a single entity just makes it so much more simpler. Some applications use multiple stores, but I haven't found a use case for this developing with Polymer-Redux.
Just a following note: There is no right or wrong way to create your Mixins. You can create as many as you wish and have multiple stores with them. That choice is up to the developer, you.
const storeA = createStore(reducerA);
const storeB = createStore(reducerB);
// ...storeZ
const ReduxMixinA = PolymerRedux(storeA);
const ReduxMixinB = PolymerRedux(storeB);
// ...ReduxMixinZ
class ElementA extends ReduxMixinA(Poymer.Element) {}
class ElementB extends ReduxMixinB(Polymer.Element) {}
// ...ElementZ
This is perfectly fine, tho personally I wouldn't do it.
Let's say you have a component for the to-do list and a component for rendering a single to-do item. You pass the item to be rendered from the list component to the renderer using polymer binding and you implement the list in which is the natural polymer way : using a dom-repeat (or an iron-list).
You also want that checking an item its state toggles from done to undone. How can you do this using a single store or a selector?
Keep in mind that the renderer has no way to decide which specific Todo is rendering apart from the injection from the list component. In particular the index is not on the global state but is simply the dom-repeat index during the rendering.
My solution so far is that the renderer will manage a local store and notifies events upwards thus the global store gets updated in turn.
But I'm curious to know if there are other ways that will allow to maintain list and rendered component decoupled and using natural polymer constructs like binding.
For instance I wouldn't consider a nice solution passing the renderer index instead of the object itself
My 2 cents:
The same challenges surely also apply to React components in combination with Redux and it might be worth checking out how it was solved there. As far as I know the current best practice is to split the React components into "dumb" presentational components and "smart" container components (https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0#.ffzyxvtbq)
The container components are redux state aware and the presentational components only have local state.
I use this pattern for a polymer/redux app and it works quit well. The container components are coupled to the app's state tree shape while the presentational components could be used in other apps where the state tree might look completely different if they have a well defined API.
Tnx @timeu
It's an interesting approach. Sometimes though we have subcomponents that are complex enough worth having a local store. I think that mixing those two approaches could be useful.
I'm still not understanding exactly what you are trying to achieve. Am I on the correct lines of:
<x-app/>
Application<x-todos/>
Todo List<x-todo-item/>
Todo Item<x-todo-decoupled/>
Decoupled Todo Item
You wish to do the following:
- There are n todos.
<x-app/>
will select todos, i.<x-todos/>
will render todos, i.<x-todo-item/>
will render an item from todos, i, using<dom-repeat/>
.<x-todo-decoupled/>
will render ANY selected item from ANY todos.
The decoupled item can be an item from another todo list, doesn't have to be the same todo list as what the application is currently rendering.
If you confirm this, I can rustle up how I personally would achieve this with a single store.