question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Why redux calls all reducers every time an action is dispatched ? Meanwhile mostly in real world app we just want to update a specific state in the store with a specific reducer ?

See original GitHub issue

Is it good for performance when a large app has over 100 reducers, when it calls 100 reducers with 99 redundant calls.

As I read from the source code, whenever dispatch an action with a specific type to the store, it will call the combination reducer function and loop through all over the reducers and call each one to find the matching action type which time complexity is O(n). But in real world app, for myself, I mostly just need to update a specific state in the store at a specific reducer and with specific action.

Here is a snippet of code in combineReducers.ts

return function combination(
    state: StateFromReducersMapObject<typeof reducers> = {},
    action: AnyAction
  ) {
    if (shapeAssertionError) {
      throw shapeAssertionError
    }

    if (process.env.NODE_ENV !== 'production') {
      const warningMessage = getUnexpectedStateShapeWarningMessage(
        state,
        finalReducers,
        action,
        unexpectedKeyCache
      )
      if (warningMessage) {
        warning(warningMessage)
      }
    }

    let hasChanged = false
    const nextState: StateFromReducersMapObject<typeof reducers> = {}
    for (let i = 0; i < finalReducerKeys.length; i++) {
      const key = finalReducerKeys[i]
      const reducer = finalReducers[key]
      const previousStateForKey = state[key]
      const nextStateForKey = reducer(previousStateForKey, action)
      if (typeof nextStateForKey === 'undefined') {
        const errorMessage = getUndefinedStateErrorMessage(key, action)
        throw new Error(errorMessage)
      }
      nextState[key] = nextStateForKey
      hasChanged = hasChanged || nextStateForKey !== previousStateForKey
    }
    hasChanged =
      hasChanged || finalReducerKeys.length !== Object.keys(state).length
    return hasChanged ? nextState : state
  }

So I do some experiment in the code, when dispatching an action, I add one more field call targetState which is a specific state key to let the store knows which state I want to update and where to find the exact reducer and just call it, so that time complexity now is O(1).

this is my code, it just for experiment, so it might be not good enough.

dispatch({type: 'ADD_TODO', targetState: 'todos'})
    let hasChanged = false
    let nextState: StateFromReducersMapObject<typeof reducers> = {}

    if (action.targetState) {
      nextState = { ...state }
      const reducer = finalReducers[action.targetState]
      const prevTargetState = state[action.targetState]
      const nextTargetState = reducer(prevTargetState, action)
      if (typeof nextTargetState === 'undefined') {
        const errorMessage = getUndefinedStateErrorMessage(
          action.targetState,
          action
        )
        throw new Error(errorMessage)
      }
      nextState[action.targetState] = nextTargetState
      hasChanged = hasChanged || nextTargetState !== prevTargetState
    } else {
      for (let i = 0; i < finalReducerKeys.length; i++) {
        const key = finalReducerKeys[i]
        const reducer = finalReducers[key]
        const previousStateForKey = state[key]
        const nextStateForKey = reducer(previousStateForKey, action)
        if (typeof nextStateForKey === 'undefined') {
          const errorMessage = getUndefinedStateErrorMessage(key, action)
          throw new Error(errorMessage)
        }
        nextState[key] = nextStateForKey
        hasChanged = hasChanged || nextStateForKey !== previousStateForKey
      }
      hasChanged =
        hasChanged || finalReducerKeys.length !== Object.keys(state).length
    }
    return hasChanged ? nextState : state

Thank you for reading

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (1 by maintainers)

github_iconTop GitHub Comments

3reactions
markeriksoncommented, Jan 21, 2021
1reaction
NguyenChiTrung1310commented, Jan 21, 2021

donotknow

Read more comments on GitHub >

github_iconTop Results From Across the Web

Redux Fundamentals, Part 3: State, Actions, and Reducers
Reducers are functions that take the current state and an action as arguments, and return a new state result. In other words, (state,...
Read more >
Actions and reducers: updating state - Human Redux
Speaking of the code that uses the action to update our application state, in Redux terminology this part is called a "reducer." Reducers....
Read more >
What is Redux? Store, Actions, and Reducers Explained ...
Note here that state in redux is immutable. So, the reducers make a copy of the entire current state first, make the necessary...
Read more >
async_redux | Flutter Package
If you want to change the store state you must "dispatch" some action. In AsyncRedux all actions extend ReduxAction . The reducer of...
Read more >
Replacing React's Redux library with the useReducer Hook
When you pass an action (the result of an action creator) into a reducer, it is the action type that determines what will...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found