> For the complete documentation index, see [llms.txt](https://bryan-guner.gitbook.io/my-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bryan-guner.gitbook.io/my-docs/redux/docs-68/md-docs/reusing-reducer-logic.md).

# reusing-reducer-logic

[**Redux**](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/index.html)

[Getting Started](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/getting-started.html)[Tutorial](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-1-overview-concepts.html)[API](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/api-reference.html)[FAQ](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq.html)[Best Practices](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/style-guide/style-guide.html)[GitHub](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/github.com/reduxjs/redux.html)[Need help?](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/getting-started.html#help-and-discussion)

🌜

🌞

Search

[**Redux**](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/index.html)

* [Getting Started](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/getting-started.html)
* [Tutorial](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-1-overview-concepts.html)
* [API](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/api-reference.html)
* [FAQ](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq.html)
* [Best Practices](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/style-guide/style-guide.html)
* [GitHub](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/github.com/reduxjs/redux.html)
* [Need help?](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/getting-started.html#help-and-discussion)
* [Introduction](#!)
  * [Getting Started with Redux](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/getting-started.html)
  * [Installation](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/installation.html)
  * [Core Concepts](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/core-concepts.html)
  * [Learning Resources](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/learning-resources.html)
  * [Ecosystem](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/ecosystem.html)
  * [Examples](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/examples.html)
* [Tutorials](#!)
  * [Tutorials Index](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/index.html)
  * [Quick Start](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/quick-start.html)
  * [TypeScript Quick Start](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/typescript-quick-start.html)
  * [Redux Essentials](#!)
    * [Redux Overview and Concepts](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-1-overview-concepts.html)
    * [Redux App Structure](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-2-app-structure.html)
    * [Basic Redux Data Flow](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-3-data-flow.html)
    * [Using Redux Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-4-using-data.html)
    * [Async Logic and Data Fetching](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-5-async-logic.html)
    * [Performance and Normalizing Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-6-performance-normalization.html)
  * [Redux Fundamentals](#!)
    * [Redux Overview](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/fundamentals/part-1-overview.html)
    * [Redux Concepts and Data Flow](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/fundamentals/part-2-concepts-data-flow.html)
    * [State, Actions, and Reducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/fundamentals/part-3-state-actions-reducers.html)
    * [Store](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/fundamentals/part-4-store.html)
    * [UI and React](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/fundamentals/part-5-ui-react.html)
    * [Async Logic and Data Fetching](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/fundamentals/part-6-async-logic.html)
    * [Standard Redux Patterns](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/fundamentals/part-7-standard-patterns.html)
    * [Modern Redux with Redux Toolkit](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/fundamentals/part-8-modern-redux.html)
* [Recipes](#!)
  * [Recipes: Index](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/recipe-index.html)
  * [Configuring Your Store](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/configuring-your-store.html)
  * [Usage With TypeScript](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/usage-with-typescript.html)
  * [Migrating to Redux](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/migrating-to-redux.html)
  * [Using Object Spread Operator](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/using-object-spread-operator.html)
  * [Reducing Boilerplate](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/reducing-boilerplate.html)
  * [Server Rendering](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/server-rendering.html)
  * [Writing Tests](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/writing-tests.html)
  * [Computing Derived Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/computing-derived-data.html)
  * [Implementing Undo History](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/implementing-undo-history.html)
  * [Isolating Redux Sub-Apps](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/isolating-redux-sub-apps.html)
  * [Code Splitting](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/code-splitting.html)
  * [Troubleshooting](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/troubleshooting.html)
  * [Structuring Reducers](#!)
    * [Structuring Reducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/structuring-reducers.html)
    * [Prerequisite Concepts](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/prerequisite-concepts.html)
    * [Basic Reducer Structure](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/basic-reducer-structure.html)
    * [Splitting Reducer Logic](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/splitting-reducer-logic.html)
    * [Refactoring Reducers Example](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/refactoring-reducer-example.html)
    * [Using combineReducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/using-combinereducers.html)
    * [Beyond combineReducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/beyond-combinereducers.html)
    * [Normalizing State Shape](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/normalizing-state-shape.html)
    * [Updating Normalized Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/updating-normalized-data.html)
    * [Reusing Reducer Logic](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/reusing-reducer-logic.html)
    * [Immutable Update Patterns](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/immutable-update-patterns.html)
    * [Initializing State](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/initializing-state.html)
* [Understanding Redux](#!)
  * [Thinking in Redux](#!)
    * [Motivation](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/understanding/thinking-in-redux/motivation.html)
    * [Three Principles](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/understanding/thinking-in-redux/three-principles.html)
    * [Glossary](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/understanding/thinking-in-redux/glossary.html)
  * [History and Design](#!)
    * [Prior Art](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/understanding/history-and-design/prior-art.html)
    * [Middleware](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/understanding/history-and-design/middleware.html)
* [FAQ](#!)
  * [FAQ Index](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq.html)
  * [General](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/general.html)
  * [Reducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/reducers.html)
  * [Organizing State](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/organizing-state.html)
  * [Store Setup](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/store-setup.html)
  * [Actions](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/actions.html)
  * [Immutable Data](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/immutable-data.html)
  * [Code Structure](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/code-structure.html)
  * [Performance](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/performance.html)
  * [Design Decisions](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/design-decisions.html)
  * [React Redux](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/react-redux.html)
  * [Miscellaneous](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq/miscellaneous.html)
* [Style Guide](#!)
  * [Style Guide: Best Practices](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/style-guide/style-guide.html)
* [API Reference](#!)
  * [API Reference](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/api-reference.html)
  * [createStore](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/createstore.html)
  * [Store](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/store.html)
  * [combineReducers](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/combinereducers.html)
  * [applyMiddleware](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/applymiddleware.html)
  * [bindActionCreators](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/bindactioncreators.html)
  * [compose](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/compose.html)
* [Redux Toolkit](#!)
  * [Redux Toolkit: Overview](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/redux-toolkit/overview.html)

## Reusing Reducer Logic[#](#reusing-reducer-logic)

As an application grows, common patterns in reducer logic will start to emerge. You may find several parts of your reducer logic doing the same kinds of work for different types of data, and want to reduce duplication by reusing the same common logic for each data type. Or, you may want to have multiple "instances" of a certain type of data being handled in the store. However, the global structure of a Redux store comes with some trade-offs: it makes it easy to track the overall state of an application, but can also make it harder to "target" actions that need to update a specific piece of state, particularly if you are using `combineReducers`.

As an example, let's say that we want to track multiple counters in our application, named A, B, and C. We define our initial `counter` reducer, and we use `combineReducers` to set up our state:

function counter(state = 0, action) {

switch (action.type) {

case 'INCREMENT':

return state + 1

case 'DECREMENT':

return state - 1

default:

return state

}

}

const rootReducer = combineReducers({

counterA: counter,

counterB: counter,

counterC: counter

})

Copy

Unfortunately, this setup has a problem. Because `combineReducers` will call each slice reducer with the same action, dispatching `{type : 'INCREMENT'}` will actually cause *all three* counter values to be incremented, not just one of them. We need some way to wrap the `counter` logic so that we can ensure that only the counter we care about is updated.

### Customizing Behavior with Higher-Order Reducers[#](#customizing-behavior-with-higher-order-reducers)

As defined in [Splitting Reducer Logic](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/md-docs/splitting-reducer-logic.html), a *higher-order reducer* is a function that takes a reducer function as an argument, and/or returns a new reducer function as a result. It can also be viewed as a "reducer factory". `combineReducers` is one example of a higher-order reducer. We can use this pattern to create specialized versions of our own reducer functions, with each version only responding to specific actions.

The two most common ways to specialize a reducer are to generate new action constants with a given prefix or suffix, or to attach additional info inside the action object. Here's what those might look like:

function createCounterWithNamedType(counterName = '') {

return function counter(state = 0, action) {

switch (action.type) {

case \`INCREMENT\_${counterName}\`:

return state + 1

case \`DECREMENT\_${counterName}\`:

return state - 1

default:

return state

}

}

}

function createCounterWithNameData(counterName = '') {

return function counter(state = 0, action) {

const { name } = action

if (name !== counterName) return state

switch (action.type) {

case \`INCREMENT\`:

return state + 1

case \`DECREMENT\`:

return state - 1

default:

return state

}

}

}

Copy

We should now be able to use either of these to generate our specialized counter reducers, and then dispatch actions that will affect the portion of the state that we care about:

const rootReducer = combineReducers({

counterA: createCounterWithNamedType('A'),

counterB: createCounterWithNamedType('B'),

counterC: createCounterWithNamedType('C')

})

store.dispatch({ type: 'INCREMENT\_B' })

console.log(store.getState())

// {counterA : 0, counterB : 1, counterC : 0}

Copy

We could also vary the approach somewhat, and create a more generic higher-order reducer that accepts both a given reducer function and a name or identifier:

function counter(state = 0, action) {

switch (action.type) {

case 'INCREMENT':

return state + 1

case 'DECREMENT':

return state - 1

default:

return state

}

}

function createNamedWrapperReducer(reducerFunction, reducerName) {

return (state, action) => {

const { name } = action

const isInitializationCall = state === undefined

if (name !== reducerName && !isInitializationCall) return state

return reducerFunction(state, action)

}

}

const rootReducer = combineReducers({

counterA: createNamedWrapperReducer(counter, 'A'),

counterB: createNamedWrapperReducer(counter, 'B'),

counterC: createNamedWrapperReducer(counter, 'C')

})

Copy

You could even go as far as to make a generic filtering higher-order reducer:

function createFilteredReducer(reducerFunction, reducerPredicate) {

return (state, action) => {

const isInitializationCall = state === undefined;

const shouldRunWrappedReducer = reducerPredicate(action) || isInitializationCall;

return shouldRunWrappedReducer ? reducerFunction(state, action) : state;

}

}

const rootReducer = combineReducers({

// check for suffixed strings

counterA : createFilteredReducer(counter, action => action.type.endsWith('\_A')),

// check for extra data in the action

counterB : createFilteredReducer(counter, action => action.name === 'B'),

// respond to all 'INCREMENT' actions, but never 'DECREMENT'

counterC : createFilteredReducer(counter, action => action.type === 'INCREMENT')

};

Copy

These basic patterns allow you to do things like having multiple instances of a smart connected component within the UI, or reuse common logic for generic capabilities such as pagination or sorting.

In addition to generating reducers this way, you might also want to generate action creators using the same approach, and could generate them both at the same time with helper functions. See [Action/Reducer Generators](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/markerikson/redux-ecosystem-links/blob/master/action-reducer-generators.html) and [Reducers](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/markerikson/redux-ecosystem-links/blob/master/reducers.html) libraries for action/reducer utilities.

### Collection / Item Reducer Pattern[#](#collection--item-reducer-pattern)

This pattern allows you to have multiple states and use a common reducer to update each state based on an additional parameter inside the action object.

function counterReducer(state, action) {

switch(action.type) {

case "INCREMENT" : return state + 1;

case "DECREMENT" : return state - 1;

}

}

function countersArrayReducer(state, action) {

switch(action.type) {

case "INCREMENT":

case "DECREMENT":

return state.map( (counter, index) => {

if(index !== action.index) return counter;

return counterReducer(counter, action);

});

default:

return state;

}

}

function countersMapReducer(state, action) {

switch(action.type) {

case "INCREMENT":

case "DECREMENT":

return {

...state,

state\[action.name] : counterReducer(state\[action.name], action)

};

default:

return state;

}

}

Copy

Previous

« Updating Normalized Data

Next

Immutable Update Patterns »

* [Customizing Behavior with Higher-Order Reducers](#customizing-behavior-with-higher-order-reducers)
* [Collection / Item Reducer Pattern](#collection--item-reducer-pattern)

**Docs**

* [Getting Started](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/getting-started.html)
* [Tutorial](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/tutorials/essentials/part-1-overview-concepts.html)
* [FAQ](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/faq.html)
* [API Reference](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/api/api-reference.html)

**Community**

* [Reactiflux Discord](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/discord.com/invite/0ZcbPKXt5bZ6au5t.html)
* [Stack Overflow](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/stackoverflow.com/questions/tagged/redux.html)
* [Feedback](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/introduction/getting-started.html#help-and-discussion)

**More**

* [GitHub](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/github.com/reduxjs/redux.html)
* [![Deploys by Netlify](https://github.com/bgoonz/Learning-Redux/blob/master/www.netlify.com/img/global/badges/netlify-color-accent.svg)](https://github.com/bgoonz/Learning-Redux/blob/master/www.netlify.com/index.html)

[![Redux Logo](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg) Copyright © 2015–2021 Dan Abramov and the Redux documentation authors.](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/index.html)
