# ecosystem

[![Redux Logo](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg)**Redux**](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/index.html)

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

🌜

🌞

Search

[![Redux Logo](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg)**Redux**](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/index.html)

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

## Ecosystem[#](#ecosystem)

Redux is a tiny library, but its contracts and APIs are carefully chosen to spawn an ecosystem of tools and extensions, and the community has created a wide variety of helpful addons, libraries, and tools. You don't need to use any of these addons to use Redux, but they can help make it easier to implement features and solve problems in your application.

For an extensive catalog of libraries, addons, and tools related to Redux, check out the [Redux Ecosystem Links](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/markerikson/redux-ecosystem-links.html) list. Also, the [React/Redux Links](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/markerikson/react-redux-links.html) list contains tutorials and other useful resources for anyone learning React or Redux.

This page lists some of the Redux-related addons that the Redux maintainers have vetted personally, or that have shown widespread adoption in the community. Don't let this discourage you from trying the rest of them! The ecosystem is growing too fast, and we have a limited time to look at everything. Consider these the “staff picks”, and don't hesitate to submit a PR if you've built something wonderful with Redux.

### Table of Contents[#](#table-of-contents)

* [Ecosystem](#ecosystem)
  * [Table of Contents](#table-of-contents)
  * [Library Integration and Bindings](#library-integration-and-bindings)
  * [Reducers](#reducers)
    * [Reducer Combination](#reducer-combination)
    * [Reducer Composition](#reducer-composition)
    * [Higher-Order Reducers](#higher-order-reducers)
  * [Actions](#actions)
  * [Utilities](#utilities)
  * [Store](#store)
    * [Change Subscriptions](#change-subscriptions)
    * [Batching](#batching)
    * [Persistence](#persistence)
  * [Immutable Data](#immutable-data)
    * [Data Structures](#data-structures)
    * [Immutable Update Utilities](#immutable-update-utilities)
    * [Immutable/Redux Interop](#immutableredux-interop)
  * [Side Effects](#side-effects)
    * [Widely Used](#widely-used)
    * [Promises](#promises)
  * [Middleware](#middleware)
    * [Networks and Sockets](#networks-and-sockets)
    * [Async Behavior](#async-behavior)
    * [Analytics](#analytics)
  * [Entities and Collections](#entities-and-collections)
  * [Component State and Encapsulation](#component-state-and-encapsulation)
  * [Dev Tools](#dev-tools)
    * [Debuggers and Viewers](#debuggers-and-viewers)
    * [DevTools Monitors](#devtools-monitors)
    * [Logging](#logging)
    * [Mutation Detection](#mutation-detection)
  * [Testing](#testing)
  * [Routing](#routing)
  * [Forms](#forms)
  * [Higher-Level Abstractions](#higher-level-abstractions)
  * [Community Conventions](#community-conventions)

### Library Integration and Bindings[#](#library-integration-and-bindings)

[**reduxjs/react-redux**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/react-redux.html)\
The official React bindings for Redux, maintained by the Redux team

[**angular-redux/ng-redux**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/angular-redux/ng-redux.html)\
Angular 1 bindings for Redux

[**ember-redux/ember-redux**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/ember-redux/ember-redux.html)\
Ember bindings for Redux

[**glimmer-redux/glimmer-redux**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/glimmer-redux/glimmer-redux.html)\
Redux bindings for Ember's Glimmer component engine

[**tur-nr/polymer-redux**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/tur-nr/polymer-redux.html)\
Redux bindings for Polymer

[**lastmjs/redux-store-element**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/lastmjs/redux-store-element.html) Redux bindings for custom elements

### Reducers[#](#reducers)

**Reducer Combination**[**#**](#reducer-combination)

[**ryo33/combineSectionReducers**](https://github.com/bgoonz/Learning-Redux/blob/master/gitlab.com/ryo33/combine-section-reducers.html)\
An expanded version of `combineReducers`, which allows passing `state` as a third argument to all slice reducers.

[**KodersLab/topologically-combine-reducers**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/KodersLab/topologically-combine-reducers.html)\
A `combineReducers` variation that allows defining cross-slice dependencies for ordering and data passing

var masterReducer = topologicallyCombineReducers(

{ auth, users, todos },

// define the dependency tree

{ auth: \['users'], todos: \['auth'] }

)

Copy

**Reducer Composition**[**#**](#reducer-composition)

[**acdlite/reduce-reducers**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-utilities/reduce-reducers.html)\
Provides sequential composition of reducers at the same level

const combinedReducer = combineReducers({ users, posts, comments })

const rootReducer = reduceReducers(combinedReducer, otherTopLevelFeatureReducer)

Copy

[**mhelmer/redux-xforms**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/mhelmer/redux-xforms.html)\
A collection of composable reducer transformers

const createByFilter = (predicate, mapActionToKey) =>

compose(

withInitialState({}), // inject initial state as {}

withFilter(predicate), // let through if action has filterName

updateSlice(mapActionToKey), // update a single key in the state

isolateSlice(mapActionToKey) // run the reducer on a single state slice

)

Copy

[**adrienjt/redux-data-structures**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/adrienjt/redux-data-structures.html)\
Reducer factory functions for common data structures: counters, maps, lists (queues, stacks), sets

const myCounter = counter({

incrementActionTypes: \['INCREMENT'],

decrementActionTypes: \['DECREMENT']

})

Copy

**Higher-Order Reducers**[**#**](#higher-order-reducers)

[**omnidan/redux-undo**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/omnidan/redux-undo.html)\
Effortless undo/redo and action history for your reducers

[**omnidan/redux-ignore**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/omnidan/redux-ignore.html)\
Ignore redux actions by array or filter function

[**omnidan/redux-recycle**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/omnidan/redux-recycle.html)\
Reset the redux state on certain actions

[**ForbesLindesay/redux-optimist**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/ForbesLindesay/redux-optimist.html)\
A reducer enhancer to enable type-agnostic optimistic updates

### Actions[#](#actions)

[**reduxactions/redux-actions**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-utilities/redux-actions.html)\
Flux Standard Action utilities for Redux

const increment = createAction('INCREMENT')

const reducer = handleActions({ \[increment]: (state, action) => state + 1 }, 0)

const store = createStore(reducer)

store.dispatch(increment())

Copy

[**BerkeleyTrue/redux-create-types**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/BerkeleyTrue/redux-create-types.html)\
Creates standard and async action types based on namespaces

export const types = createTypes(

\['openModal', createAsyncTypes('fetch')],

'app'

)

// { openModal : "app.openModal", fetch : { start : "app.fetch.start", complete: 'app.fetch.complete' } }

Copy

[**maxhallinan/kreighter**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/maxhallinan/kreighter.html)\
Generates action creators based on types and expected fields

const formatTitle = (id, title) => ({

id,

title: toTitleCase(title)

})

const updateBazTitle = fromType('UPDATE\_BAZ\_TITLE', formatTitle)

updateBazTitle(1, 'foo bar baz')

// -> { type: 'UPDATE\_BAZ\_TITLE', id: 1, title: 'Foo Bar Baz', }

Copy

### Utilities[#](#utilities)

[**reduxjs/reselect**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/reselect.html)\
Creates composable memoized selector functions for efficiently deriving data from the store state

const taxSelector = createSelector(

\[subtotalSelector, taxPercentSelector],

(subtotal, taxPercent) => subtotal \* (taxPercent / 100)

)

Copy

[**paularmstrong/normalizr**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/paularmstrong/normalizr.html)\
Normalizes nested JSON according to a schema

const user = new schema.Entity('users')

const comment = new schema.Entity('comments', { commenter: user })

const article = new schema.Entity('articles', {

author: user,

comments: \[comment]

})

const normalizedData = normalize(originalData, article)

Copy

[**planttheidea/selectorator**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/planttheidea/selectorator.html)\
Abstractions over Reselect for common selector use cases

const getBarBaz = createSelector(

\['foo.bar', 'baz'],

(bar, baz) => \`${bar} ${baz}\`

)

getBarBaz({ foo: { bar: 'a' }, baz: 'b' }) // "a b"

Copy

### Store[#](#store)

**Change Subscriptions**[**#**](#change-subscriptions)

[**jprichardson/redux-watch**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/ExodusMovement/redux-watch.html)\
Watch for state changes based on key paths or selectors

let w = watch(() => mySelector(store.getState()))

store.subscribe(

w((newVal, oldVal) => {

console.log(newval, oldVal)

})

)

Copy

[**ashaffer/redux-subscribe**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/ashaffer/redux-subscribe.html)\
Centralized subscriptions to state changes based on paths

store.dispatch( subscribe("users.byId.abcd", "subscription1", () => {} );

Copy

**Batching**[**#**](#batching)

[**tappleby/redux-batched-subscribe**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/tappleby/redux-batched-subscribe.html)\
Store enhancer that can debounce subscription notifications

const debounceNotify = \_.debounce(notify => notify())

const store = createStore(

reducer,

initialState,

batchedSubscribe(debounceNotify)

)

Copy

[**manaflair/redux-batch**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/manaflair/redux-batch.html)\
Store enhancer that allows dispatching arrays of actions

const store = createStore(reducer, reduxBatch)

store.dispatch(\[{ type: 'INCREMENT' }, { type: 'INCREMENT' }])

Copy

[**laysent/redux-batch-actions-enhancer**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/laysent/redux-batch-actions-enhancer.html)\
Store enhancer that accepts batched actions

const store = createStore(reducer, initialState, batch().enhancer)

store.dispatch(createAction({ type: 'INCREMENT' }, { type: 'INCREMENT' }))

Copy

[**tshelburne/redux-batched-actions**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/tshelburne/redux-batched-actions.html)\
Higher-order reducer that handles batched actions

const store = createStore(enableBatching(reducer), initialState)

store.dispatch(batchActions(\[{ type: 'INCREMENT' }, { type: 'INCREMENT' }]))

Copy

**Persistence**[**#**](#persistence)

[**rt2zz/redux-persist**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/rt2zz/redux-persist.html)\
Persist and rehydrate a Redux store, with many extensible options

const store = createStore(reducer, autoRehydrate())

persistStore(store)

Copy

[**react-stack/redux-storage**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/react-stack/redux-storage.html)\
Persistence layer for Redux with flexible backends

const reducer = storage.reducer(combineReducers(reducers))

const engine = createEngineLocalStorage('my-save-key')

const storageMiddleware = storage.createMiddleware(engine)

const store = createStore(reducer, applyMiddleware(storageMiddleware))

Copy

[**redux-offline/redux-offline**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-offline/redux-offline.html)\
Persistent store for Offline-First apps, with support for optimistic UIs

const store = createStore(reducer, offline(offlineConfig))

store.dispatch({

type: 'FOLLOW\_USER\_REQUEST',

meta: { offline: { effect: {}, commit: {}, rollback: {} } }

})

Copy

### Immutable Data[#](#immutable-data)

[**ImmerJS/immer**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/immerjs/immer.html)\
Immutable updates with normal mutative code, using Proxies

const nextState = produce(baseState, draftState => {

draftState.push({ todo: 'Tweet about it' })

draftState\[1].done = true

})

Copy

### Side Effects[#](#side-effects)

**Widely Used**[**#**](#widely-used)

[**gaearon/redux-thunk**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/redux-thunk.html)\
Dispatch functions, which are called and given `dispatch` and `getState` as parameters. This acts as a loophole for AJAX calls and other async behavior.

**Best for**: getting started, simple async and complex synchronous logic.

function fetchData(someValue) {

return (dispatch, getState) => {

dispatch({type : "REQUEST\_STARTED"});

myAjaxLib.post("/someEndpoint", {data : someValue})

.then(response => dispatch({type : "REQUEST\_SUCCEEDED", payload : response})

.catch(error => dispatch({type : "REQUEST\_FAILED", error : error});

};

}

function addTodosIfAllowed(todoText) {

return (dispatch, getState) => {

const state = getState();

if(state.todos.length < MAX\_TODOS) {

dispatch({type : "ADD\_TODO", text : todoText});

}

}

}

Copy

[**redux-saga/redux-saga**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-saga/redux-saga.html)\
Handle async logic using synchronous-looking generator functions. Sagas return descriptions of effects, which are executed by the saga middleware, and act like "background threads" for JS applications.

**Best for**: complex async logic, decoupled workflows

function\* fetchData(action) {

const { someValue } = action

try {

const response = yield call(myAjaxLib.post, '/someEndpoint', {

data: someValue

})

yield put({ type: 'REQUEST\_SUCCEEDED', payload: response })

} catch (error) {

yield put({ type: 'REQUEST\_FAILED', error: error })

}

}

function\* addTodosIfAllowed(action) {

const { todoText } = action

const todos = yield select(state => state.todos)

if (todos.length < MAX\_TODOS) {

yield put({ type: 'ADD\_TODO', text: todoText })

}

}

Copy

[**redux-observable/redux-observable**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-observable/redux-observable.html)

Handle async logic using RxJS observable chains called "epics". Compose and cancel async actions to create side effects and more.

**Best for**: complex async logic, decoupled workflows

const loginRequestEpic = action$ =>

action$

.ofType(LOGIN\_REQUEST)

.mergeMap(({ payload: { username, password } }) =>

Observable.from(postLogin(username, password))

.map(loginSuccess)

.catch(loginFailure)

)

const loginSuccessfulEpic = action$ =>

action$

.ofType(LOGIN\_SUCCESS)

.delay(2000)

.mergeMap(({ payload: { msg } }) => showMessage(msg))

const rootEpic = combineEpics(loginRequestEpic, loginSuccessfulEpic)

Copy

[**redux-loop/redux-loop**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-loop/redux-loop.html)

A port of the Elm Architecture to Redux that allows you to sequence your effects naturally and purely by returning them from your reducers. Reducers now return both a state value and a side effect description.

**Best for**: trying to be as much like Elm as possible in Redux+JS

export const reducer = (state = {}, action) => {

switch (action.type) {

case ActionType.LOGIN\_REQUEST:

const { username, password } = action.payload

return loop(

{ pending: true },

Effect.promise(loginPromise, username, password)

)

case ActionType.LOGIN\_SUCCESS:

const { user, msg } = action.payload

return loop(

{ pending: false, user },

Effect.promise(delayMessagePromise, msg, 2000)

)

case ActionType.LOGIN\_FAILURE:

return { pending: false, err: action.payload }

default:

return state

}

}

Copy

[**jeffbski/redux-logic**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/jeffbski/redux-logic.html)

Side effects lib built with observables, but allows use of callbacks, promises, async/await, or observables. Provides declarative processing of actions.

**Best for**: very decoupled async logic

const loginLogic = createLogic({

type: Actions.LOGIN\_REQUEST,

process({ getState, action }, dispatch, done) {

const { username, password } = action.payload

postLogin(username, password)

.then(

({ user, msg }) => {

dispatch(loginSucceeded(user))

setTimeout(() => dispatch(showMessage(msg)), 2000)

},

err => dispatch(loginFailure(err))

)

.then(done)

}

})

Copy

**Promises**[**#**](#promises)

[**acdlite/redux-promise**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-utilities/redux-promise.html)\
Dispatch promises as action payloads, and have FSA-compliant actions dispatched as the promise resolves or rejects.

dispatch({ type: 'FETCH\_DATA', payload: myAjaxLib.get('/data') })

// will dispatch either {type : "FETCH\_DATA", payload : response} if resolved,

// or dispatch {type : "FETCH\_DATA", payload : error, error : true} if rejected

Copy

[**lelandrichardson/redux-pack**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/lelandrichardson/redux-pack.html)\
Sensible, declarative, convention-based promise handling that guides users in a good direction without exposing the full power of dispatch.

dispatch({type : "FETCH\_DATA", payload : myAjaxLib.get("/data") });

// in a reducer:

case "FETCH\_DATA": =

return handle(state, action, {

start: prevState => ({

...prevState,

isLoading: true,

fooError: null

}),

finish: prevState => ({ ...prevState, isLoading: false }),

failure: prevState => ({ ...prevState, fooError: payload }),

success: prevState => ({ ...prevState, foo: payload }),

});

Copy

### Middleware[#](#middleware)

**Networks and Sockets**[**#**](#networks-and-sockets)

[**svrcekmichal/redux-axios-middleware**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/svrcekmichal/redux-axios-middleware.html)\
Fetches data with Axios and dispatches start/success/fail actions

export const loadCategories() => ({ type: 'LOAD', payload: { request : { url: '/categories'} } });

Copy

[**agraboso/redux-api-middleware**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/agraboso/redux-api-middleware.html)\
Reads API call actions, fetches, and dispatches FSAs

const fetchUsers = () => ({

\[CALL\_API]: {

endpoint: '<http://www.example.com/api/users>',

method: 'GET',

types: \['REQUEST', 'SUCCESS', 'FAILURE']

}

})

Copy

[**itaylor/redux-socket.io**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/itaylor/redux-socket.html)\
An opinionated connector between socket.io and redux.

const store = createStore(reducer, applyMiddleware(socketIoMiddleware))

store.dispatch({ type: 'server/hello', data: 'Hello!' })

Copy

[**tiberiuc/redux-react-firebase**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/tiberiuc/redux-react-firebase.html)\
Integration between Firebase, React, and Redux

**Async Behavior**[**#**](#async-behavior)

[**rt2zz/redux-action-buffer**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/rt2zz/redux-action-buffer.html)\
Buffers all actions into a queue until a breaker condition is met, at which point the queue is released

[**wyze/redux-debounce**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/wyze/redux-debounce.html)\
FSA-compliant middleware for Redux to debounce actions.

[**mathieudutour/redux-queue-offline**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/mathieudutour/redux-queue-offline.html)\
Queue actions when offline and dispatch them when getting back online.

**Analytics**[**#**](#analytics)

[**rangle/redux-beacon**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/rangle/redux-beacon.html)\
Integrates with any analytics services, can track while offline, and decouples analytics logic from app logic

[**markdalgleish/redux-analytics**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/markdalgleish/redux-analytics.html)\
Watches for Flux Standard Actions with meta analytics values and processes them

### Entities and Collections[#](#entities-and-collections)

[**tommikaikkonen/redux-orm**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-orm/redux-orm.html)\
A simple immutable ORM to manage relational data in your Redux store.

[**Versent/redux-crud**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/Versent/redux-crud.html)\
Convention-based actions and reducers for CRUD logic

[**kwelch/entities-reducer**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/kwelch/entities-reducer.html)\
A higher-order reducer that handles data from Normalizr

[**amplitude/redux-query**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/amplitude/redux-query.html)\
Declare colocated data dependencies with your components, run queries when components mount, perform optimistic updates, and trigger server changes with Redux actions.

[**cantierecreativo/redux-bees**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/cantierecreativo/redux-bees.html)\
Declarative JSON-API interaction that normalizes data, with a React HOC that can run queries

[**GetAmbassador/redux-clerk**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/GetAmbassador/redux-clerk.html)\
Async CRUD handling with normalization, optimistic updates, sync/async action creators, selectors, and an extendable reducer.

[**shoutem/redux-io**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/shoutem/redux-io.html)\
JSON-API abstraction with async CRUD, normalization, optimistic updates, caching, data status, and error handling.

[**jmeas/redux-resource**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/jamesplease/redux-resource.html)\
A tiny but powerful system for managing 'resources': data that is persisted to remote servers.

### Component State and Encapsulation[#](#component-state-and-encapsulation)

[**threepointone/redux-react-local**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/threepointone/redux-react-local.html)\
Local component state in Redux, with handling for component actions

@local({

ident: 'counter', initial: 0, reducer : (state, action) => action.me ? state + 1 : state }

})

class Counter extends React.Component {

Copy

[**epeli/lean-redux**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/esamattis/lean-redux.html)\
Makes component state in Redux as easy as setState

const DynamicCounters = connectLean(

scope: "dynamicCounters",

getInitialState() => ({counterCount : 1}),

addCounter, removeCounter

)(CounterList);

Copy

[**DataDog/redux-doghouse**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/DataDog/redux-doghouse.html)\
Aims to make reusable components easier to build with Redux by scoping actions and reducers to a particular instance of a component.

const scopeableActions = new ScopedActionFactory(actionCreators)

const actionCreatorsScopedToA = scopeableActions.scope('a')

actionCreatorsScopedToA.foo('bar') //{ type: SET\_FOO, value: 'bar', scopeID: 'a' }

const boundScopeableActions = bindScopedActionFactories(

scopeableActions,

store.dispatch

)

const scopedReducers = scopeReducers(reducers)

Copy

### Dev Tools[#](#dev-tools)

**Debuggers and Viewers**[**#**](#debuggers-and-viewers)

[**reduxjs/redux-devtools**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/redux-devtools.html)

Dan Abramov's original Redux DevTools implementation, built for in-app display of state and time-travel debugging

[**zalmoxisus/redux-devtools-extension**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/zalmoxisus/redux-devtools-extension.html)

Mihail Diordiev's browser extension, which bundles multiple state monitor views and adds integration with the browser's own dev tools

[**infinitered/reactotron**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/infinitered/reactotron.html)

A cross-platform Electron app for inspecting React and React Native apps, including app state, API requests, perf, errors, sagas, and action dispatching.

**DevTools Monitors**[**#**](#devtools-monitors)

[**Log Monitor**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-log-monitor.html)\
The default monitor for Redux DevTools with a tree view

[**Dock Monitor**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-dock-monitor.html)\
A resizable and movable dock for Redux DevTools monitors

[**Slider Monitor**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/calesce/redux-slider-monitor.html)\
A custom monitor for Redux DevTools to replay recorded Redux actions

[**Diff Monitor**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/whetstone/redux-devtools-diff-monitor.html)\
A monitor for Redux DevTools that diffs the Redux store mutations between actions

[**Filterable Log Monitor**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/bvaughn/redux-devtools-filterable-log-monitor/index.html)\
Filterable tree view monitor for Redux DevTools

[**Filter Actions**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/zalmoxisus/redux-devtools-filter-actions.html)\
Redux DevTools composable monitor with the ability to filter actions

**Logging**[**#**](#logging)

[**evgenyrodionov/redux-logger**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/LogRocket/redux-logger.html)\
Logging middleware that shows actions, states, and diffs

[**inakianduaga/redux-state-history**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/inakianduaga/redux-state-history.html)\
Enhancer that provides time-travel and efficient action recording capabilities, including import/export of action logs and action playback.

[**joshwcomeau/redux-vcr**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/joshwcomeau/redux-vcr.html)\
Record and replay user sessions in real-time

[**socialtables/redux-unhandled-action**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/socialtables/redux-unhandled-action.html)\
Warns about actions that produced no state changes in development

**Mutation Detection**[**#**](#mutation-detection)

[**leoasis/redux-immutable-state-invariant**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/leoasis/redux-immutable-state-invariant.html)\
Middleware that throws an error when you try to mutate your state either inside a dispatch or between dispatches.

[**flexport/mutation-sentinel**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/flexport/mutation-sentinel.html)\
Helps you deeply detect mutations at runtime and enforce immutability in your codebase.

[**mmahalwy/redux-pure-connect**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/mmahalwy/redux-pure-connect.html)\
Check and log whether react-redux's connect method is passed `mapState` functions that create impure props.

### Testing[#](#testing)

[**arnaudbenard/redux-mock-store**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/reduxjs/redux-mock-store.html)\
A mock store that saves dispatched actions in an array for assertions

[**Workable/redux-test-belt**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/Workable/redux-test-belt.html)\
Extends the store API to make it easier assert, isolate, and manipulate the store

[**conorhastings/redux-test-recorder**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/conorhastings/redux-test-recorder.html)\
Middleware to automatically generate reducers tests based on actions in the app

[**wix/redux-testkit**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/wix/redux-testkit.html)\
Complete and opinionated testkit for testing Redux projects (reducers, selectors, actions, thunks)

[**jfairbank/redux-saga-test-plan**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/jfairbank/redux-saga-test-plan.html)\
Makes integration and unit testing of sagas a breeze

### Routing[#](#routing)

[**supasate/connected-react-router**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/supasate/connected-react-router.html) Synchronize React Router 4 state with your Redux store.

[**faceyspacey/redux-first-router**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/faceyspacey/redux-first-router.html)\
Seamless Redux-first routing. Think of your app in states, not routes, not components, while keeping the address bar in sync. Everything is state. Connect your components and just dispatch flux standard actions.

### Forms[#](#forms)

[**erikras/redux-form**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-form/redux-form.html)\
A full-featured library to enable a React HTML form to store its state in Redux.

[**davidkpiano/react-redux-form**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/davidkpiano/react-redux-form.html)\
React Redux Form is a collection of reducer creators and action creators that make implementing even the most complex and custom forms with React and Redux simple and performant.

### Higher-Level Abstractions[#](#higher-level-abstractions)

[**keajs/kea**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/keajs/kea.html)\
An abstraction over Redux, Redux-Saga and Reselect. Provides a framework for your app’s actions, reducers, selectors and sagas. It empowers Redux, making it as simple to use as setState. It reduces boilerplate and redundancy, while retaining composability.

[**TheComfyChair/redux-scc**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/TheComfyChair/redux-scc.html)\
Takes a defined structure and uses 'behaviors' to create a set of actions, reducer responses and selectors.

[**Bloomca/redux-tiles**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/Bloomca/redux-tiles.html)\
Provides minimal abstraction on top of Redux, to allow easy composability, easy async requests, and sane testability.

### Community Conventions[#](#community-conventions)

[**Flux Standard Action**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/redux-utilities/flux-standard-action.html)\
A human-friendly standard for Flux action objects

[**Canonical Reducer Composition**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/gajus/canonical-reducer-composition.html)\
An opinionated standard for nested reducer composition

[**Ducks: Redux Reducer Bundles**](https://github.com/bgoonz/Learning-Redux/blob/master/github.com/erikras/ducks-modular-redux.html)\
A proposal for bundling reducers, action types and actions

Previous

« Learning Resources

Next

Examples »

* [Table of Contents](#table-of-contents)
* [Library Integration and Bindings](#library-integration-and-bindings)
* [Reducers](#reducers)
* [Actions](#actions)
* [Utilities](#utilities)
* [Store](#store)
* [Immutable Data](#immutable-data)
* [Side Effects](#side-effects)
* [Middleware](#middleware)
* [Entities and Collections](#entities-and-collections)
* [Component State and Encapsulation](#component-state-and-encapsulation)
* [Dev Tools](#dev-tools)
* [Testing](#testing)
* [Routing](#routing)
* [Forms](#forms)
* [Higher-Level Abstractions](#higher-level-abstractions)
* [Community Conventions](#community-conventions)

**Docs**

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

**Community**

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

**More**

* [GitHub](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/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/official/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg)![Redux Logo](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/official/d33wubrfki0l68.cloudfront.net/0834d0215db51e91525a25acf97433051f280f2f/c30f5/img/redux.svg)](https://github.com/bgoonz/Learning-Redux/blob/master/DOCS/index.html)

Copyright © 2015–2021 Dan Abramov and the Redux documentation authors.
