-
-
Notifications
You must be signed in to change notification settings - Fork 15.2k
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
Reducer without switch #1167
Comments
The whole point of Flux/Redux is to decouple actions and reducers. There may be many independent reducers handling one action, and there may be many independent actions handled by one reducer. This is what makes Flux/Redux scale because big teams can work on overlapping features without constant merge conflicts, as state mutation logic is kept separate even if it is caused by the same actions. You also lose the ability to serialize and record/replay actions because they are not plain objects any more in your example. Enabling this was another big constraint of Redux. Please read this:
|
Think of action as a "message". The action doesn't know how the state changes. It's precisely reducers' job. Otherwise your reducers don't seem to contain code at all. Also don't forget that reducers can be composed further than a single level. What you propose doesn't work with reducer composition because you're effectively hardcoding reducer structure into the action objects. |
I see. Thank you for the quick feedback @gaearon 👍 |
Well, personally I hate switch so I use plain objects instead: const actionHandlers = {
[ADD_TODO] (state, todo) {
// do stuff
},
[REMOVE_TODO] (state, id) {
// do stuff
}
}
const reducer = (state = initialState, action) => {
const { type, payload } = action
const actionHandler = actionHandlers[type]
if (actionHandler) {
return actionHandler(state, payload)
}
return state
} |
@negamaxi What does this syntax mean that you use?
|
@batcer it's a way to create a method of a certain name stored in a constant: const ADD_TODO = 'addTodo';
const handlers = {
[ADD_TODO] () {}
} ...is the same as... const handlers = {
addTodo() {}
} |
As reading from the docs you could avoid using
switch
with a function that maps action types to handlers. But still I'm not fully convinced with that approach.In order to avoid those long switch statements, I suggest injecting the dependency of the reducers right into the actions.
The actions now will know how to change the state per each reducer. The reducer will just call them accordingly. This way, the reducer would follow the Open/Closed principle (Motivation by Uncle Bob: https://youtu.be/TMuno5RZNeE?t=3605)
I found this architecture much better. Take the case your system requires a new feature where 3 reducers listen to the same action. Then you would need to modify those reducers -- adding a new case on each switch statement.
Following the style I propose, you would only need to create the action with the reducers all in the same place. Example:
Here you could see a refactor of the todomvc example using this idea.
Thoughts?
The text was updated successfully, but these errors were encountered: