Ecosystem

For an extensive catalog of libraries, addons, and tools related to Redux, check out the list. Also, the React/Redux Links 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.

Library Integration and Bindings

reduxjs/react-reduxThe official React bindings for Redux, maintained by the Redux team

Angular 1 bindings for Redux

angular-redux/storeAngular 2+ bindings for Redux

Ember bindings for Redux

glimmer-redux/glimmer-reduxRedux bindings for Ember's Glimmer component engine

Redux bindings for Polymer

lastmjs/redux-store-elementRedux bindings for custom elements

Reducers

Reducer Combination

An expanded version of , which allows passing state as a third argument to all slice reducers.

KodersLab/topologically-combine-reducersA combineReducers variation that allows defining cross-slice dependencies for ordering and data passing

Reducer Composition

acdlite/reduce-reducersProvides sequential composition of reducers at the same level

  1. const combinedReducer = combineReducers({ users, posts, comments })
  2. const rootReducer = reduceReducers(combinedReducer, otherTopLevelFeatureReducer)

A collection of composable reducer transformers

  1. const createByFilter = (predicate, mapActionToKey) =>
  2. compose(
  3. withInitialState({}), // inject initial state as {}
  4. withFilter(predicate), // let through if action has filterName
  5. updateSlice(mapActionToKey), // update a single key in the state
  6. isolateSlice(mapActionToKey) // run the reducer on a single state slice
  7. )

adrienjt/redux-data-structuresReducer factory functions for common data structures: counters, maps, lists (queues, stacks), sets

  1. const myCounter = counter({
  2. incrementActionTypes: ['INCREMENT'],
  3. decrementActionTypes: ['DECREMENT']
  4. })

Higher-Order Reducers

omnidan/redux-undoEffortless undo/redo and action history for your reducers

Ignore redux actions by array or filter function

omnidan/redux-recycleReset the redux state on certain actions

A reducer enhancer to enable type-agnostic optimistic updates

Actions

Flux Standard Action utilities for Redux

  1. const increment = createAction('INCREMENT')
  2. const reducer = handleActions({ [increment]: (state, action) => state + 1 }, 0)
  3. const store = createStore(reducer)
  4. store.dispatch(increment())

BerkeleyTrue/redux-create-typesCreates standard and async action types based on namespaces

  1. export const types = createTypes(
  2. ['openModal', createAsyncTypes('fetch')],
  3. 'app'
  4. )
  5. // { openModal : "app.openModal", fetch : { start : "app.fetch.start", complete: 'app.fetch.complete' } }

Generates action creators based on types and expected fields

  1. const formatTitle = (id, title) => ({
  2. id,
  3. title: toTitleCase(title)
  4. })
  5. const updateBazTitle = fromType('UPDATE_BAZ_TITLE', formatTitle)
  6. updateBazTitle(1, 'foo bar baz')
  7. // -> { type: 'UPDATE_BAZ_TITLE', id: 1, title: 'Foo Bar Baz', }

Utilities

Creates composable memoized selector functions for efficiently deriving data from the store state

  1. const taxSelector = createSelector(
  2. [subtotalSelector, taxPercentSelector],
  3. (subtotal, taxPercent) => subtotal * (taxPercent / 100)
  4. )

paularmstrong/normalizrNormalizes nested JSON according to a schema

  1. const user = new schema.Entity('users')
  2. const article = new schema.Entity('articles', {
  3. author: user,
  4. comments: [comment]
  5. })
  6. const normalizedData = normalize(originalData, article)

Abstractions over Reselect for common selector use cases

  1. const getBarBaz = createSelector(
  2. ['foo.bar', 'baz'],
  3. (bar, baz) => `${bar} ${baz}`
  4. )
  5. getBarBaz({ foo: { bar: 'a' }, baz: 'b' }) // "a b"

Change Subscriptions

Watch for state changes based on key paths or selectors

  1. let w = watch(() => mySelector(store.getState()))
  2. store.subscribe(
  3. w((newVal, oldVal) => {
  4. console.log(newval, oldVal)
  5. })
  6. )

ashaffer/redux-subscribeCentralized subscriptions to state changes based on paths

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

Batching

tappleby/redux-batched-subscribeStore enhancer that can debounce subscription notifications

  1. const debounceNotify = _.debounce(notify => notify())
  2. const store = createStore(
  3. reducer,
  4. initialState,
  5. batchedSubscribe(debounceNotify)
  6. )

Store enhancer that allows dispatching arrays of actions

  1. const store = createStore(reducer, reduxBatch)
  2. store.dispatch([{ type: 'INCREMENT' }, { type: 'INCREMENT' }])

laysent/redux-batch-actions-enhancerStore enhancer that accepts batched actions

Higher-order reducer that handles batched actions

  1. const store = createStore(enableBatching(reducer), initialState)
  2. store.dispatch(batchActions([{ type: 'INCREMENT' }, { type: 'INCREMENT' }]))

Persistence

Persist and rehydrate a Redux store, with many extensible options

  1. const store = createStore(reducer, autoRehydrate())
  2. persistStore(store)

react-stack/redux-storagePersistence layer for Redux with flexible backends

  1. const reducer = storage.reducer(combineReducers(reducers))
  2. const engine = createEngineLocalStorage('my-save-key')
  3. const storageMiddleware = storage.createMiddleware(engine)
  4. const store = createStore(reducer, applyMiddleware(storageMiddleware))

Persistent store for Offline-First apps, with support for optimistic UIs

  1. const store = createStore(reducer, offline(offlineConfig))
  2. store.dispatch({
  3. type: 'FOLLOW_USER_REQUEST',
  4. meta: { offline: { effect: {}, commit: {}, rollback: {} } }
  5. })

Immutable Data

Data Structures

facebook/immutable-jsImmutable persistent data collections for Javascript

  1. const map1 = Map({ a: 1, b: 2, c: 3 })
  2. const map2 = map1.set('b', 50)
  3. map1.get('b') // 2
  4. map2.get('b') // 50

Frozen immutable arrays/objects, backwards-compatible with JS

  1. const array = Immutable(['totally', 'immutable', { a: 42 }])
  2. array[0] = 'edited' // does nothing

planttheidea/crioImmutable JS objects with a natural API

  1. const foo = crio(['foo'])

Utilities for treating frozen JS objects as persistent immutable collections.

  1. const newObj = icepick.assocIn({ c: { d: 'bar' } }, ['c', 'd'], 'baz')
  2. const obj3 = icepicke.merge(obj1, obj2)

Immutable Update Utilities

Immutable updates with normal mutative code, using Proxies

  1. const nextState = produce(baseState, draftState => {
  2. draftState.push({ todo: 'Tweet about it' })
  3. draftState[1].done = true
  4. })

kolodny/immutability-helperA drop-in replacement for react-addons-update

  1. const newData = update(myData, {
  2. x: { y: { z: { $set: 7 } } },
  3. a: { b: { $push: [9] } }
  4. })
  1. const newObj = immutable(obj)
  2. .set('a.b', 'f')
  3. .del(['a', 'c', 0])
  4. .value()

Immutable version of the dot-prop lib, with some extensions

  1. const newState = dotProp.set(state, `todos.${index}.complete`, true)
  2. const endOfArray = dotProp.get(obj, 'foo.$end')

Immutable/Redux Interop

combineReducers equivalent that works with Immutable.js Maps

  1. const initialState = Immutable.Map()
  2. const rootReducer = combineReducers({})
  3. const store = createStore(rootReducer, initialState)

eadmundo/redux-seamless-immutablecombineReducers equivalent that works with seamless-immutable values

Side Effects

Widely Used

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.

  1. function fetchData(someValue) {
  2. return (dispatch, getState) => {
  3. dispatch({type : "REQUEST_STARTED"});
  4. myAjaxLib.post("/someEndpoint", {data : someValue})
  5. .then(response => dispatch({type : "REQUEST_SUCCEEDED", payload : response})
  6. .catch(error => dispatch({type : "REQUEST_FAILED", error : error});
  7. };
  8. }
  9. function addTodosIfAllowed(todoText) {
  10. return (dispatch, getState) => {
  11. const state = getState();
  12. if(state.todos.length < MAX_TODOS) {
  13. dispatch({type : "ADD_TODO", text : todoText});
  14. }
  15. }
  16. }

redux-saga/redux-sagaHandle 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

  1. function* fetchData(action) {
  2. const { someValue } = action
  3. try {
  4. const response = yield call(myAjaxLib.post, '/someEndpoint', {
  5. data: someValue
  6. })
  7. yield put({ type: 'REQUEST_SUCCEEDED', payload: response })
  8. } catch (error) {
  9. yield put({ type: 'REQUEST_FAILED', error: error })
  10. }
  11. }
  12. function* addTodosIfAllowed(action) {
  13. const { todoText } = action
  14. const todos = yield select(state => state.todos)
  15. if (todos.length < MAX_TODOS) {
  16. yield put({ type: 'ADD_TODO', text: todoText })
  17. }

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

  1. const loginRequestEpic = action$ =>
  2. action$
  3. .ofType(LOGIN_REQUEST)
  4. .mergeMap(({ payload: { username, password } }) =>
  5. Observable.from(postLogin(username, password))
  6. .map(loginSuccess)
  7. .catch(loginFailure)
  8. )
  9. const loginSuccessfulEpic = action$ =>
  10. action$
  11. .ofType(LOGIN_SUCCESS)
  12. .delay(2000)
  13. .mergeMap(({ payload: { msg } }) => showMessage(msg))
  14. const rootEpic = combineEpics(loginRequestEpic, loginSuccessfulEpic)

redux-loop/redux-loop

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

  1. export const reducer = (state = {}, action) => {
  2. switch (action.type) {
  3. case ActionType.LOGIN_REQUEST:
  4. const { username, password } = action.payload
  5. return loop(
  6. { pending: true },
  7. )
  8. case ActionType.LOGIN_SUCCESS:
  9. const { user, msg } = action.payload
  10. return loop(
  11. { pending: false, user },
  12. Effect.promise(delayMessagePromise, msg, 2000)
  13. )
  14. case ActionType.LOGIN_FAILURE:
  15. return { pending: false, err: action.payload }
  16. default:
  17. return state
  18. }
  19. }

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

  1. const loginLogic = createLogic({
  2. type: Actions.LOGIN_REQUEST,
  3. process({ getState, action }, dispatch, done) {
  4. const { username, password } = action.payload
  5. postLogin(username, password)
  6. .then(
  7. ({ user, msg }) => {
  8. dispatch(loginSucceeded(user))
  9. setTimeout(() => dispatch(showMessage(msg)), 2000)
  10. },
  11. err => dispatch(loginFailure(err))
  12. )
  13. .then(done)
  14. }
  15. })

Promises

Dispatch promises as action payloads, and have FSA-compliant actions dispatched as the promise resolves or rejects.

  1. dispatch({ type: 'FETCH_DATA', payload: myAjaxLib.get('/data') })
  2. // will dispatch either {type : "FETCH_DATA", payload : response} if resolved,
  3. // or dispatch {type : "FETCH_DATA", payload : error, error : true} if rejected

lelandrichardson/redux-packSensible, declarative, convention-based promise handling that guides users in a good direction without exposing the full power of dispatch.

  1. dispatch({type : "FETCH_DATA", payload : myAjaxLib.get("/data") });
  2. // in a reducer:
  3. case "FETCH_DATA": =
  4. return handle(state, action, {
  5. start: prevState => ({
  6. ...prevState,
  7. isLoading: true,
  8. fooError: null
  9. }),
  10. finish: prevState => ({ ...prevState, isLoading: false }),
  11. failure: prevState => ({ ...prevState, fooError: payload }),
  12. success: prevState => ({ ...prevState, foo: payload }),
  13. });

Middleware

Networks and Sockets

Fetches data with Axios and dispatches start/success/fail actions

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

agraboso/redux-api-middlewareReads API call actions, fetches, and dispatches FSAs

  1. const fetchUsers = () => ({
  2. [CALL_API]: {
  3. endpoint: 'http://www.example.com/api/users',
  4. method: 'GET',
  5. types: ['REQUEST', 'SUCCESS', 'FAILURE']
  6. }
  7. })

An opinionated connector between socket.io and redux.

  1. const store = createStore(reducer, applyMiddleware(socketIoMiddleware))
  2. store.dispatch({ type: 'server/hello', data: 'Hello!' })

tiberiuc/redux-react-firebaseIntegration between Firebase, React, and Redux

Async Behavior

rt2zz/redux-action-bufferBuffers all actions into a queue until a breaker condition is met, at which point the queue is released

FSA-compliant middleware for Redux to debounce actions.

mathieudutour/redux-queue-offlineQueue actions when offline and dispatch them when getting back online.

Analytics

rangle/redux-beaconIntegrates with any analytics services, can track while offline, and decouples analytics logic from app logic

Analytics and tracking with an easy API for writing your own adapters

markdalgleish/redux-analyticsWatches for Flux Standard Actions with meta analytics values and processes them

Entities and Collections

tommikaikkonen/redux-ormA simple immutable ORM to manage relational data in your Redux store.

Convention-based actions and reducers for CRUD logic

kwelch/entities-reducerA higher-order reducer that handles data from Normalizr

Declare colocated data dependencies with your components, run queries when components mount, perform optimistic updates, and trigger server changes with Redux actions.

cantierecreativo/redux-beesDeclarative JSON-API interaction that normalizes data, with a React HOC that can run queries

Async CRUD handling with normalization, optimistic updates, sync/async action creators, selectors, and an extendable reducer.

shoutem/redux-ioJSON-API abstraction with async CRUD, normalization, optimistic updates, caching, data status, and error handling.

A tiny but powerful system for managing 'resources': data that is persisted to remote servers.

tonyhb/redux-ui"Block-level scoping" for UI state. Decorated components declare data fields, which become props and can be updated by nested children.

  1. @ui({
  2. key: 'some-name',
  3. state: { uiVar1: '', uiVar2: (props, state) => state.someValue },
  4. reducer: (state, action) => {}
  5. })
  6. class YourComponent extends React.Component {}

Local component state in Redux, with handling for component actions

  1. @local({
  2. ident: 'counter', initial: 0, reducer : (state, action) => action.me ? state + 1 : state }
  3. })
  4. class Counter extends React.Component {

epeli/lean-reduxMakes component state in Redux as easy as setState

  1. const DynamicCounters = connectLean(
  2. scope: "dynamicCounters",
  3. getInitialState() => ({counterCount : 1}),
  4. addCounter, removeCounter
  5. )(CounterList);

Aims to make reusable components easier to build with Redux by scoping actions and reducers to a particular instance of a component.

  1. const scopeableActions = new ScopedActionFactory(actionCreators)
  2. const actionCreatorsScopedToA = scopeableActions.scope('a')
  3. actionCreatorsScopedToA.foo('bar') //{ type: SET_FOO, value: 'bar', scopeID: 'a' }
  4. const boundScopeableActions = bindScopedActionFactories(
  5. scopeableActions,
  6. store.dispatch
  7. const scopedReducers = scopeReducers(reducers)

Dev Tools

Debuggers and Viewers

reduxjs/redux-devtools

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

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

infinitered/reactotron

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

Log MonitorThe default monitor for Redux DevTools with a tree view

A resizable and movable dock for Redux DevTools monitors

Slider MonitorA custom monitor for Redux DevTools to replay recorded Redux actions

A custom monitor for Redux DevTools that lets you filter actions, inspect diffs, and pin deep paths in the state to observe their changes

Diff MonitorA monitor for Redux DevTools that diffs the Redux store mutations between actions

Filterable tree view monitor for Redux DevTools

Chart MonitorA chart monitor for Redux DevTools

Redux DevTools composable monitor with the ability to filter actions

Logging

Logging middleware that shows actions, states, and diffs

inakianduaga/redux-state-historyEnhancer that provides time-travel and efficient action recording capabilities, including import/export of action logs and action playback.

Record and replay user sessions in real-time

socialtables/redux-unhandled-actionWarns about actions that produced no state changes in development

Mutation Detection

leoasis/redux-immutable-state-invariantMiddleware that throws an error when you try to mutate your state either inside a dispatch or between dispatches.

Helps you deeply detect mutations at runtime and enforce immutability in your codebase.

mmahalwy/redux-pure-connectCheck and log whether react-redux's connect method is passed functions that create impure props.

Testing

arnaudbenard/redux-mock-storeA mock store that saves dispatched actions in an array for assertions

Extends the store API to make it easier assert, isolate, and manipulate the store

conorhastings/redux-test-recorderMiddleware to automatically generate reducers tests based on actions in the app

Complete and opinionated testkit for testing Redux projects (reducers, selectors, actions, thunks)

jfairbank/redux-saga-test-planMakes integration and unit testing of sagas a breeze

Routing

supasate/connected-react-routerSynchronize React Router 4 state with your Redux store.

A tiny router for Redux applications that lets the URL do the talking

faceyspacey/redux-first-routerSeamless 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

erikras/redux-formA full-featured library to enable a React HTML form to store its state in Redux.

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.

keajs/keaAn 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.

A simplified layer over Redux. No action creators or explicit dispatching, with a built-in simple side effects system.

TheComfyChair/redux-sccTakes a defined structure and uses 'behaviors' to create a set of actions, reducer responses and selectors.

Provides minimal abstraction on top of Redux, to allow easy composability, easy async requests, and sane testability.

Community Conventions

A human-friendly standard for Flux action objects

Canonical Reducer CompositionAn opinionated standard for nested reducer composition

A proposal for bundling reducers, action types and actions