Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redux a better way to write reducers?

Tags:

I think the Redux holds a lot of great value however the main issue for me lies with how reducers are written today:

const addToDoReducer = (state, action) => {
    switch (action.type) {
        case ADD_TODO:
            return Object.assign({}, state, {
                todos: todos(state.todos, action)
            })
        case TOGGLE_TODO:
            return Object.assign({}, state, {
                todos: todos(state.todos, action)
            })
        default:
            return state
    }
}
  • reducers are too generic (you can literally write bloated reducer that handles all sorts of different actions and easily create a mess) if nothing else this breaks single responsibility principle
  • switch statement impose maintenance-side effects like changes to one case could break other cases (e.g. code that already works)
  • always repeated "default: return state" (fails DRY)
  • all reducers are always invoked (calling functions to do nothing is just wrong)

... this at the end reducers become the weak/bridle spot of the project

Q: Is there a better way/option to write reducer that:

  • gets invoked only for specific action (based on the type of action object)
  • eliminates switch statement

something more like this:

const addToDoReducer = (state:toDoState, action:addAction) =>
{
    return { ...state, toDos: [...state.toDos, action.toDoObject] };
}

Or is there a library that does this already?

like image 622
Andrej K Avatar asked Mar 01 '18 19:03

Andrej K


People also ask

How many reducers should I use Redux?

A Redux app really only has one reducer function: the "root reducer" function that you will pass to createStore later on. That one root reducer function is responsible for handling all of the actions that are dispatched, and calculating what the entire new state result should be every time.

Does Redux reduce performance?

While it's certainly possible for each of these to become a performance concern in sufficiently complex situations, there's nothing inherently slow or inefficient about how Redux is implemented.

Is reducer same as Redux?

Reducers are the only way to change states in Redux. It is the only place where you can write logic and calculations. Reducer function will accept the previous state of app and action being dispatched, calculate the next state and returns the new object.

Why reducers should be pure?

Pure reducers have no side effects and enable things like time-travelling. They make reasoning about application behavior easier.


1 Answers

Please read the "Reducing Boilerplate" docs page for examples of how you can write your own reducer utilities, such as a function that takes a lookup table of action types to specific reducer functions for each type. Specifically:

function createReducer(initialState, handlers) {
  return function reducer(state = initialState, action) {
    if (handlers.hasOwnProperty(action.type)) {
      return handlers[action.type](state, action)
    } else {
      return state
    }
  }
}

The "Structuring Reducers" docs section also gives instructions and ideas on ways to organize your reducer logic.

For further information, please see:

  • The Redux FAQ entry on "calling all reducers" and performance
  • The Redux FAQ entry on using switch statements
  • My blog post The Tao of Redux, Part 2 - Practice and Philosophy, which specifically discusses the fact that whether you use switch statements and how you write your reducer logic is entirely up to you
  • The Redux addons catalog list of reducer utility libraries

Remember: Redux calls your root reducer function, which is code that you have written. How that reducer does its work is your choice. If you don't like switch statements, don't write them. If you find the code repetitive, write factory functions.

like image 188
markerikson Avatar answered Sep 20 '22 12:09

markerikson