-
-
Notifications
You must be signed in to change notification settings - Fork 15.3k
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
Isomorphic states actions #1511
Comments
We generally recommend you to normalize your state instead: {
todosById: {
0: { id: 0, text: 'lol' },
1: { id: 1, text: 'hi' },
2: { id: 2, text: 'wow' }
},
highPriorityIds: [0, 1],
lowPriorityIds: [2]
} Then there is no duplication of logic. Hope this helps! |
While the cart example shows some insight on how to manage nested states it still doesn't allow the same action to operate on different but identical states. I would have to define an action creator and an action type for each of the existing actions whereas using something like a namespace would allow me to define upon which part of the state I wish to dispatch an action. Take this example const initialState = {
A: {/*...*/},
B: {/*...*/},
C: {/*...*/}
}
const TO_A = 'TO_A'
const TO_B = 'TO_B'
const TO_C = 'TO_C'
const doToA = () => {
type: TO_A
}
const doToB = () => {
type: TO_B
}
const doToC = () => {
type: TO_C
}
const reducer = (state, action) {
switch action.type {
case TO_A: return {
...state,
A: commonReducer(state.A, action)
}
case TO_B: return {
...state,
B: commonReducer(state.B, action)
}
case TO_A: return {
...state,
C: commonReducer(state.C, action)
}
}
} While it could be something like const DO_ACTION = 'DO_ACTION';
function doAction() {
type: DO_ACTION,
namespace: this
}
const reducer = (state, action) {
switch action.type {
case DO_ACTION: return {
...state,
[action.namespace]: actionReducer(state[action.namespace], action)
}
}
}
// and to dispatch the action
dispatch('A'::doAction())
dispatch('B'::doAction())
dispatch('C'::doAction()) |
This is a little bit too abstract. Can you help me understand what you’re aiming for specifically? |
Reusing reducers and action creators across similar states to share logic that applies to them, also allowing to modify any given target inner state without the need of adding more logic to the application. |
Have you looked at reducers in |
Going to reference #822 and #1528 since they do a better job explaining the issue with non-rehusable reducers that operate on top of abstract, isomorphic states. |
Usind redux I've realized there are many times where my state structure ends up with very similar sub states that could reuse the same logic applied to similar states.
Both of these so-called "sub-states" could use the same logic to add, remove or clear todos from the list. However the naive approach leads to a very unscalable result
So each substate has its own "same-action" identifier, with its own action creator, and "almost-same" reduce logic.
First step could be delegating the reducing to another reducer
But this still doesnt cut it, there's a lot of code repetition and merging all action handling into one big
ADD_TODO
case would cause unavoidable pollution to the action's body in order to differentiate which action changes which part of the state.So I came up with this solution, adding context to the action creator could allow actions to identify the state they act upon by diving into the state structure with the use of namespaces.
A namespace would be the key of the child state within the parent state
Using a namespace as the context to the dispatch function binds the child state as the state passed on to the reducer
Using this idea with the previous example it ends up being like this
The only reason this isn't fully possible at the moment is because
bindActionCreators
doesn't allow the resulting wrapped action creators to have context, would this be possible without breaking the current API? Is this context based approach something frowned upon within applications that use redux?EDIT: changed syntax from
NAMESPACE::dispatch(actionCreator())
todispatch(NAMESPACE::actionCreator())
The text was updated successfully, but these errors were encountered: