react-redux Documentation

Official React bindings for Redux

23,455 stars TypeScript TypeScript 1 file Β· ~24,829 tokens #react#redux
RAW Doc

File: README.md

React Redux

Official React bindings for Redux.
Performant and flexible.



Installation

Create a React Redux App

The recommended way to start new apps with React and Redux is by using our official Redux+TS template for Vite, or by creating a new Next.js project using Next's with-redux template.

Both of these already have Redux Toolkit and React-Redux configured appropriately for that build tool, and come with a small example app that demonstrates how to use several of Redux Toolkit's features.

bash
# Vite with our Redux+TS template
# (using the `degit` tool to clone and extract the template)
npx degit reduxjs/redux-templates/packages/vite-template-redux my-app

# Next.js using the `with-redux` template
npx create-next-app --example with-redux my-app

An Existing React App

React Redux 9.0 requires React 18 or later

To use React Redux with your React app, install it as a dependency:

bash
# If you use npm:
npm install react-redux

# Or if you use Yarn:
yarn add react-redux

You'll also need to install Redux and set up a Redux store in your app.

This assumes that you’re using npm package manager
with a module bundler like Webpack or
Browserify to consume CommonJS
modules
.

If you don’t yet use npm or a modern module bundler, and would rather prefer a single-file UMD build that makes ReactRedux available as a global object, you can grab a pre-built version from cdnjs. We don’t recommend this approach for any serious application, as most of the libraries complementary to Redux are only available on npm.

Documentation

The React Redux docs are published at https://react-redux.js.org .

How Does It Work?

The post The History and Implementation of React-Redux
explains what it does, how it works, and how the API and implementation have evolved over time.

There's also a Deep Dive into React-Redux talk that covers some of the same material at a higher level.

License

MIT


File: docs/introduction/getting-started.md


id: getting-started title: Getting Started with React Redux hide_title: true sidebar_label: Getting Started

 

import LiteYouTubeEmbed from 'react-lite-youtube-embed';
import 'react-lite-youtube-embed/dist/LiteYouTubeEmbed.css'

Getting Started with React Redux

React Redux is the official React UI bindings layer for Redux. It lets your React components read data from a Redux store, and dispatch actions to the store to update state.

Installation

React Redux 8.x requires React 16.8.3 or later / React Native 0.59 or later, in order to make use of React Hooks.

Create a React Redux App

The recommended way to start new apps with React and Redux is by using our official Redux+TS template for Vite, or by creating a new Next.js project using Next's with-redux template.

Both of these already have Redux Toolkit and React-Redux configured appropriately for that build tool, and come with a small example app that demonstrates how to use several of Redux Toolkit's features.

bash
# Vite with our Redux+TS template
# (using the `degit` tool to clone and extract the template)
npx degit reduxjs/redux-templates/packages/vite-template-redux my-app

# Next.js using the `with-redux` template
npx create-next-app --example with-redux my-app

We do not currently have official React Native templates, but recommend these templates for standard React Native and for Expo:

An Existing React App

To use React Redux with your React app, install it as a dependency:

bash
# If you use npm:
npm install react-redux

# Or if you use Yarn:
yarn add react-redux

You'll also need to install Redux and set up a Redux store in your app.

React-Redux v8 is written in TypeScript, so all types are automatically included.

API Overview

`Provider`

React Redux includes a `` component, which makes the Redux store available to the rest of your app:

jsx
import React from 'react'
import ReactDOM from 'react-dom/client'

import { Provider } from 'react-redux'
import store from './store'

import App from './App'

// As of React 18
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  
    <App />
  ,
)

Hooks

React Redux provides a pair of custom React hooks that allow your React components to interact with the Redux store.

useSelector reads a value from the store state and subscribes to updates, while useDispatch returns the store's dispatch method to let you dispatch actions.

jsx
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import {
  decrement,
  increment,
  incrementByAmount,
  incrementAsync,
  selectCount,
} from './counterSlice'
import styles from './Counter.module.css'

export function Counter() {
  const count = useSelector(selectCount)
  const dispatch = useDispatch()

  return (
    
      
         dispatch(increment())}
        >
          +
        
        {count}
         dispatch(decrement())}
        >
          -
        
      
      {/* omit additional rendering output here */}
    
  )
}

Learning React Redux

Learn Modern Redux Livestream

Redux maintainer Mark Erikson appeared on the "Learn with Jason" show to explain how we recommend using Redux today. The show includes a live-coded example app that shows how to use Redux Toolkit and React-Redux hooks with TypeScript, as well as the new RTK Query data fetching APIs.

See the "Learn Modern Redux" show notes page for a transcript and links to the example app source.

Help and Discussion

The #redux channel of the Reactiflux Discord community is our official resource for all questions related to learning and using Redux. Reactiflux is a great place to hang out, ask questions, and learn - come join us!

You can also ask questions on Stack Overflow using the #redux tag.

Docs Translations


File: docs/introduction/why-use-react-redux.md


id: why-use-react-redux title: Why Use React Redux? hide_title: true sidebar_label: Why Use React Redux?

 

Why Use React Redux?

Redux itself is a standalone library that can be used with any UI layer or framework, including React, Angular, Vue, Ember, and vanilla JS. Although Redux and React are commonly used together, they are independent of each other.

If you are using Redux with any kind of UI framework, you will normally use a "UI binding" library to tie Redux together with your UI framework, rather than directly interacting with the store from your UI code.

React Redux is the official Redux UI binding library for React. If you are using Redux and React together, you should also use React Redux to bind these two libraries.

To understand why you should use React Redux, it may help to understand what a "UI binding library" does.

:::info

If you have questions about whether you should use Redux in general, please see these articles for discussion of when and why you might want to use Redux, and how it's intended to be used:

:::

Integrating Redux with a UI

Using Redux with any UI layer requires the same consistent set of steps:

  1. Create a Redux store
  2. Subscribe to updates
  3. Inside the subscription callback:
    1. Get the current store state
    2. Extract the data needed by this piece of UI
    3. Update the UI with the data
  4. If necessary, render the UI with initial state
  5. Respond to UI inputs by dispatching Redux actions

While it is possible to write this logic by hand, doing so would become very repetitive. In addition, optimizing UI performance would require complicated logic.

The process of subscribing to the store, checking for updated data, and triggering a re-render can be made more generic and reusable. A UI binding library like React Redux handles the store interaction logic, so you don't have to write that code yourself.

:::info

For a deeper look at how React Redux works internally and how it handles the store interaction for you, see Idiomatic Redux: The History and Implementation of React Redux.

:::

Reasons to Use React Redux

It is the Official Redux UI Bindings for React

While Redux can be used with any UI layer, it was originally designed and intended for use with React. There are UI binding layers for many other frameworks, but React Redux is maintained directly by the Redux team.

As the official Redux binding for React, React Redux is kept up-to-date with any API changes from either library, to ensure that your React components behave as expected. Its intended usage adopts the design principles of React - writing declarative components.

It Implements Performance Optimizations For You

React is generally fast, but by default any updates to a component will cause React to re-render all of the components inside that part of the component tree. This does require work, and if the data for a given component hasn't changed, then re-rendering is likely some wasted effort because the requested UI output would be the same.

If performance is a concern, the best way to improve performance is to skip unnecessary re-renders, so that components only re-render when their data has actually changed. React Redux implements many performance optimizations internally, so that your own component only re-renders when it actually needs to.

In addition, by connecting multiple components in your React component tree, you can ensure that each connected component only extracts the specific pieces of data from the store state that are needed by that component. This means that your own component will need to re-render less often, because most of the time those specific pieces of data haven't changed.

Community Support

As the official binding library for React and Redux, React Redux has a large community of users. This makes it easier to ask for help, learn about best practices, use libraries that build on top of React Redux, and reuse your knowledge across different applications.

Understanding React Redux

Community Resources


File: docs/api/batch.md


id: batch title: batch sidebar_label: batch() hide_title: true

 

`batch()`

js
batch((fn: () => void))

added in v7.0.0

:::info

If you're using React 18, you do not need to use the batch API. React 18 automatically batches all state updates, no matter where they're queued.

:::

React's unstable_batchedUpdates() API allows any React updates in an event loop tick to be batched together into a single render pass. React already uses this internally for its own event handler callbacks. This API is actually part of the renderer packages like ReactDOM and React Native, not the React core itself.

Since React-Redux needs to work in both ReactDOM and React Native environments, we've taken care of importing this API from the correct renderer at build time for our own use. We also now re-export this function publicly ourselves, renamed to batch(). You can use it to ensure that multiple actions dispatched outside of React only result in a single render update, like this:

ts
import { batch } from 'react-redux'

function myThunk() {
  return (dispatch, getState) => {
    // should only result in one combined re-render, not two
    batch(() => {
      dispatch(increment())
      dispatch(increment())
    })
  }
}

References


File: docs/api/connect.md


id: connect title: Connect sidebar_label: connect() hide_title: true

 

`connect()`

:::tip

connect still works and is supported in React-Redux 8.x. However, we recommend using the hooks API as the default.

:::

Overview

The connect() function connects a React component to a Redux store.

It provides its connected component with the pieces of the data it needs from the store, and the functions it can use to dispatch actions to the store.

It does not modify the component class passed to it; instead, it returns a new, connected component class that wraps the component you passed in.

js
function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)

The mapStateToProps and mapDispatchToProps deals with your Redux store’s state and dispatch, respectively. state and dispatch will be supplied to your mapStateToProps or mapDispatchToProps functions as the first argument.

The returns of mapStateToProps and mapDispatchToProps are referred to internally as stateProps and dispatchProps, respectively. They will be supplied to mergeProps, if defined, as the first and the second argument, where the third argument will be ownProps. The combined result, commonly referred to as mergedProps, will then be supplied to your connected component.

`connect()` Parameters

connect accepts four different parameters, all optional. By convention, they are called:

  1. mapStateToProps?: Function
  2. mapDispatchToProps?: Function | Object
  3. mergeProps?: Function
  4. options?: Object

`mapStateToProps?: (state, ownProps?) => Object`

If a mapStateToProps function is specified, the new wrapper component will subscribe to Redux store updates. This means that any time the store is updated, mapStateToProps will be called. The results of mapStateToProps must be a plain object, which will be merged into the wrapped component’s props. If you don't want to subscribe to store updates, pass null or undefined in place of mapStateToProps.

Parameters

  1. state: Object
  2. ownProps?: Object

A mapStateToProps function takes a maximum of two parameters. The number of declared function parameters (a.k.a. arity) affects when it will be called. This also determines whether the function will receive ownProps. See notes here.

`state`

If your mapStateToProps function is declared as taking one parameter, it will be called whenever the store state changes, and given the store state as the only parameter.

js
const mapStateToProps = (state) => ({ todos: state.todos })

`ownProps`

If your mapStateToProps function is declared as taking two parameters, it will be called whenever the store state changes or when the wrapper component receives new props (based on shallow equality comparisons). It will be given the store state as the first parameter, and the wrapper component's props as the second parameter.

The second parameter is normally referred to as ownProps by convention.

js
const mapStateToProps = (state, ownProps) => ({
  todo: state.todos[ownProps.id],
})

Returns

Your mapStateToProps functions are expected to return an object. This object, normally referred to as stateProps, will be merged as props to your connected component. If you define mergeProps, it will be supplied as the first parameter to mergeProps.

The return of the mapStateToProps determine whether the connected component will re-render (details here).

For more details on recommended usage of mapStateToProps, please refer to our guide on using mapStateToProps.

You may define mapStateToProps and mapDispatchToProps as a factory function, i.e., you return a function instead of an object. In this case your returned function will be treated as the real mapStateToProps or mapDispatchToProps, and be called in subsequent calls. You may see notes on Factory Functions or our guide on performance optimizations.

`mapDispatchToProps?: Object | (dispatch, ownProps?) => Object`

Conventionally called mapDispatchToProps, this second parameter to connect() may either be an object, a function, or not supplied.

Your component will receive dispatch by default, i.e., when you do not supply a second parameter to connect():

js
// do not pass `mapDispatchToProps`
connect()(MyComponent)
connect(mapState)(MyComponent)
connect(mapState, null, mergeProps, options)(MyComponent)

If you define a mapDispatchToProps as a function, it will be called with a maximum of two parameters.

Parameters

  1. dispatch: Function
  2. ownProps?: Object

`dispatch`

If your mapDispatchToProps is declared as a function taking one parameter, it will be given the dispatch of your store.

js
const mapDispatchToProps = (dispatch) => {
  return {
    // dispatching plain actions
    increment: () => dispatch({ type: 'INCREMENT' }),
    decrement: () => dispatch({ type: 'DECREMENT' }),
    reset: () => dispatch({ type: 'RESET' }),
  }
}

`ownProps`

If your mapDispatchToProps function is declared as taking two parameters, it will be called with dispatch as the first parameter and the props passed to the wrapper component as the second parameter, and will be re-invoked whenever the connected component receives new props.

The second parameter is normally referred to as ownProps by convention.

ts
// binds on component re-rendering
 this.props.toggleTodo(this.props.todoId)} />

// binds on `props` change
const mapDispatchToProps = (dispatch, ownProps) => ({
  toggleTodo: () => dispatch(toggleTodo(ownProps.todoId)),
})

The number of declared function parameters of mapDispatchToProps determines whether they receive ownProps. See notes here.

Returns

Your mapDispatchToProps functions are expected to return an object. Each fields of the object should be a function, calling which is expected to dispatch an action to the store.

The return of your mapDispatchToProps functions are regarded as dispatchProps. It will be merged as props to your connected component. If you define mergeProps, it will be supplied as the second parameter to mergeProps.

js
const createMyAction = () => ({ type: 'MY_ACTION' })
const mapDispatchToProps = (dispatch, ownProps) => {
  const boundActions = bindActionCreators({ createMyAction }, dispatch)
  return {
    dispatchPlainObject: () => dispatch({ type: 'MY_ACTION' }),
    dispatchActionCreatedByActionCreator: () => dispatch(createMyAction()),
    ...boundActions,
    // you may return dispatch here
    dispatch,
  }
}

For more details on recommended usage, please refer to our guide on using mapDispatchToProps.

You may define mapStateToProps and mapDispatchToProps as a factory function, i.e., you return a function instead of an object. In this case your returned function will be treated as the real mapStateToProps or mapDispatchToProps, and be called in subsequent calls. You may see notes on Factory Functions or our guide on performance optimizations.

Object Shorthand Form

mapDispatchToProps may be an object where each field is an action creator.

js
import { addTodo, deleteTodo, toggleTodo } from './actionCreators'

const mapDispatchToProps = {
  addTodo,
  deleteTodo,
  toggleTodo,
}

export default connect(null, mapDispatchToProps)(TodoApp)

In this case, React-Redux binds the dispatch of your store to each of the action creators using bindActionCreators. The result will be regarded as dispatchProps, which will be either directly merged to your connected components, or supplied to mergeProps as the second argument.

js
// internally, React-Redux calls bindActionCreators
// to bind the action creators to the dispatch of your store
bindActionCreators(mapDispatchToProps, dispatch)

We also have a section in our mapDispatchToProps guide on the usage of object shorthand form here.

`mergeProps?: (stateProps, dispatchProps, ownProps) => Object`

If specified, defines how the final props for your own wrapped component are determined. If you do not provide mergeProps, your wrapped component receives { ...ownProps, ...stateProps, ...dispatchProps } by default.

Parameters

mergeProps should be specified with maximum of three parameters. They are the result of mapStateToProps(), mapDispatchToProps(), and the wrapper component's props, respectively:

  1. stateProps
  2. dispatchProps
  3. ownProps

The fields in the plain object you return from it will be used as the props for the wrapped component. You may specify this function to select a slice of the state based on props, or to bind action creators to a particular variable from props.

Returns

The return value of mergeProps is referred to as mergedProps and the fields will be used as the props for the wrapped component.

Note: Creating new values in mergeProps will cause re-renders. It is recommended that you memoize fields in order to avoid unnecessary re-renders.

`options?: Object`

js
{
  context?: Object,
  areStatesEqual?: Function,
  areOwnPropsEqual?: Function,
  areStatePropsEqual?: Function,
  areMergedPropsEqual?: Function,
  forwardRef?: boolean,
}

`context: Object`

Note: This parameter is supported in >= v6.0 only

React-Redux v6 allows you to supply a custom context instance to be used by React-Redux.
You need to pass the instance of your context to both `` and your connected component.
You may pass the context to your connected component either by passing it here as a field of option, or as a prop to your connected component in rendering.

js
// const MyContext = React.createContext();
connect(mapStateToProps, mapDispatchToProps, null, { context: MyContext })(
  MyComponent,
)

`areStatesEqual: (next: Object, prev: Object, nextOwnProps: Object, prevOwnProps: Object) => boolean`

  • default value: strictEqual: (next, prev) => prev === next

Compares incoming store state to its previous value.

js
const areStatesEqual = (next, prev) =>
  prev.entities.todos === next.entities.todos

You may wish to override areStatesEqual if your mapStateToProps function is computationally expensive and is also only concerned with a small slice of your state. The example above will effectively ignore state changes for everything but that slice of state. Additionally, areStatesEqual provides nextOwnProps and prevOwnProps to allow for more effective scoping of your state which your connected component is interested in, if needed.

This would likely impact the other equality checks as well, depending on your mapStateToProps function.

`areOwnPropsEqual: (next: Object, prev: Object) => boolean`

  • default value: shallowEqual: (objA, objB) => boolean
    ( returns true when each field of the objects is equal )

Compares incoming props to its previous value.

You may wish to override areOwnPropsEqual as a way to whitelist incoming props. You'd also have to implement mapStateToProps, mapDispatchToProps and mergeProps to also whitelist props. (It may be simpler to achieve this other ways, for example by using recompose's mapProps.)

`areStatePropsEqual: (next: Object, prev: Object) => boolean`

  • type: function
  • default value: shallowEqual

Compares the result of mapStateToProps to its previous value.

`areMergedPropsEqual: (next: Object, prev: Object) => boolean`

  • default value: shallowEqual

Compares the result of mergeProps to its previous value.

You may wish to override areStatePropsEqual to use strictEqual if your mapStateToProps uses a memoized selector that will only return a new object if a relevant prop has changed. This would be a very slight performance improvement, since would avoid extra equality checks on individual props each time mapStateToProps is called.

You may wish to override areMergedPropsEqual to implement a deepEqual if your selectors produce complex props. ex: nested objects, new arrays, etc. (The deep equal check may be faster than just re-rendering.)

`forwardRef: boolean`

Note: This parameter is supported in >= v6.0 only

If {forwardRef : true} has been passed to connect, adding a ref to the connected wrapper component will actually return the instance of the wrapped component.

`connect()` Returns

The return of connect() is a wrapper function that takes your component and returns a wrapper component with the additional props it injects.

js
import { login, logout } from './actionCreators'

const mapState = (state) => state.user
const mapDispatch = { login, logout }

// first call: returns a hoc that you can use to wrap any component
const connectUser = connect(mapState, mapDispatch)

// second call: returns the wrapper component with mergedProps
// you may use the hoc to enable different components to get the same behavior
const ConnectedUserLogin = connectUser(Login)
const ConnectedUserProfile = connectUser(Profile)

In most cases, the wrapper function will be called right away, without being saved in a temporary variable:

js
import { login, logout } from './actionCreators'

const mapState = (state) => state.user
const mapDispatch = { login, logout }

// call connect to generate the wrapper function, and immediately call
// the wrapper function to generate the final wrapper component.

export default connect(mapState, mapDispatch)(Login)

Example Usage

Because connect is so flexible, it may help to see some additional examples of how it can be called:

  • Inject just dispatch and don't listen to store
js
export default connect()(TodoApp)
  • Inject all action creators (addTodo, completeTodo, ...) without subscribing to the store
js
import * as actionCreators from './actionCreators'

export default connect(null, actionCreators)(TodoApp)
  • Inject dispatch and every field in the global state

Don’t do this! It kills any performance optimizations because TodoApp will rerender after every state change.
It’s better to have more granular connect() on several components in your view hierarchy that each only listen to a relevant slice of the state.

js
// don't do this!
export default connect((state) => state)(TodoApp)
  • Inject dispatch and todos
js
function mapStateToProps(state) {
  return { todos: state.todos }
}

export default connect(mapStateToProps)(TodoApp)
  • Inject todos and all action creators
js
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
  return { todos: state.todos }
}

export default connect(mapStateToProps, actionCreators)(TodoApp)
  • Inject todos and all action creators (addTodo, completeTodo, ...) as actions
js
import * as actionCreators from './actionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return { actions: bindActionCreators(actionCreators, dispatch) }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • Inject todos and a specific action creator (addTodo)
js
import { addTodo } from './actionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ addTodo }, dispatch)
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • Inject todos and specific action creators (addTodo and deleteTodo) with shorthand syntax
js
import { addTodo, deleteTodo } from './actionCreators'

function mapStateToProps(state) {
  return { todos: state.todos }
}

const mapDispatchToProps = {
  addTodo,
  deleteTodo,
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • Inject todos, todoActionCreators as todoActions, and counterActionCreators as counterActions
js
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return {
    todoActions: bindActionCreators(todoActionCreators, dispatch),
    counterActions: bindActionCreators(counterActionCreators, dispatch),
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • Inject todos, and todoActionCreators and counterActionCreators together as actions
js
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(
      { ...todoActionCreators, ...counterActionCreators },
      dispatch,
    ),
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • Inject todos, and all todoActionCreators and counterActionCreators directly as props
js
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(
    { ...todoActionCreators, ...counterActionCreators },
    dispatch,
  )
}

export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
  • Inject todos of a specific user depending on props
js
import * as actionCreators from './actionCreators'

function mapStateToProps(state, ownProps) {
  return { todos: state.todos[ownProps.userId] }
}

export default connect(mapStateToProps)(TodoApp)
  • Inject todos of a specific user depending on props, and inject props.userId into the action
js
import * as actionCreators from './actionCreators'

function mapStateToProps(state) {
  return { todos: state.todos }
}

function mergeProps(stateProps, dispatchProps, ownProps) {
  return Object.assign({}, ownProps, {
    todos: stateProps.todos[ownProps.userId],
    addTodo: (text) => dispatchProps.addTodo(ownProps.userId, text),
  })
}

export default connect(mapStateToProps, actionCreators, mergeProps)(TodoApp)

Notes

The Arity of `mapToProps` Functions

The number of declared function parameters of mapStateToProps and mapDispatchToProps determines whether they receive ownProps

Note: ownProps is not passed to mapStateToProps and mapDispatchToProps if the formal definition of the function contains one mandatory parameter (function has length 1). For example, functions defined like below won't receive ownProps as the second argument. If the incoming value of ownProps is undefined, the default argument value will be used.

js
function mapStateToProps(state) {
  console.log(state) // state
  console.log(arguments[1]) // undefined
}

const mapStateToProps = (state, ownProps = {}) => {
  console.log(state) // state
  console.log(ownProps) // {}
}

Functions with no mandatory parameters or two parameters*will receive ownProps.

js
const mapStateToProps = (state, ownProps) => {
  console.log(state) // state
  console.log(ownProps) // ownProps
}

function mapStateToProps() {
  console.log(arguments[0]) // state
  console.log(arguments[1]) // ownProps
}

const mapStateToProps = (...args) => {
  console.log(args[0]) // state
  console.log(args[1]) // ownProps
}

Factory Functions

If your mapStateToProps or mapDispatchToProps functions return a function, they will be called once when the component instantiates, and their returns will be used as the actual mapStateToProps, mapDispatchToProps, functions respectively, in their subsequent calls.

The factory functions are commonly used with memoized selectors. This gives you the ability to create component-instance-specific selectors inside the closure:

js
const makeUniqueSelectorInstance = () =>
  createSelector([selectItems, selectItemId], (items, itemId) => items[itemId])
const makeMapState = (state) => {
  const selectItemForThisComponent = makeUniqueSelectorInstance()
  return function realMapState(state, ownProps) {
    const item = selectItemForThisComponent(state, ownProps.itemId)
    return { item }
  }
}
export default connect(makeMapState)(SomeComponent)

Legacy Version Docs

While the connect API has stayed almost entirely API-compatible between all of our major versions, there have been some small changes in options and behavior from version to version.

For details on the legacy 5.x and 6.x versions, please see these archived files in the React Redux repo:


File: docs/api/hooks.md


id: hooks title: Hooks sidebar_label: Hooks hide_title: true

 

Hooks

React's "hooks" APIs give function components the ability to use local component state, execute side effects, and more. React also lets us write custom hooks, which let us extract reusable hooks to add our own behavior on top of React's built-in hooks.

React Redux includes its own custom hook APIs, which allow your React components to subscribe to the Redux store and dispatch actions.

:::tip

We recommend using the React-Redux hooks API as the default approach in your React components.

The existing connect API still works and will continue to be supported, but the hooks API is simpler and works better with TypeScript.

:::

These hooks were first added in v7.1.0.

Using Hooks in a React Redux App

As with connect(), you should start by wrapping your entire application in a `` component to make the store available throughout the component tree:

jsx
const store = createStore(rootReducer)

// As of React 18
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  
    <App />
  ,
)

From there, you may import any of the listed React Redux hooks APIs and use them within your function components.

`useSelector()`

ts
type RootState = ReturnType<typeof store.getState>
type SelectorFn = <Selected>(state: RootState) => Selected
type EqualityFn = (a: any, b: any) => boolean
export type DevModeCheckFrequency = 'never' | 'once' | 'always'

interface UseSelectorOptions {
  equalityFn?: EqualityFn
  devModeChecks?: {
    stabilityCheck?: DevModeCheckFrequency
    identityFunctionCheck?: DevModeCheckFrequency
  }
}

const result: Selected = useSelector(
  selector: SelectorFn,
  options?: EqualityFn | UseSelectorOptions
)

Allows you to extract data from the Redux store state for use in this component, using a selector function.

:::info

The selector function should be pure since it is potentially executed multiple times and at arbitrary points in time.

See Using Redux: Deriving Data with Selectors in the Redux docs for more details on writing and using selector functions.

:::

The selector will be called with the entire Redux store state as its only argument. The selector may return any value as a result, including directly returning a value that was nested inside state, or deriving new values. The return value of the selector will be used as the return value of the useSelector() hook.

The selector will be run whenever the function component renders (unless its reference hasn't changed since a previous render of the component so that a cached result can be returned by the hook without re-running the selector). useSelector() will also subscribe to the Redux store, and run your selector whenever an action is dispatched.

When an action is dispatched, useSelector() will do a reference comparison of the previous selector result value and the current result value. If they are different, the component will be forced to re-render. If they are the same, the component will not re-render. useSelector() uses strict === reference equality checks by default, not shallow equality (see the following section for more details).

The selector is approximately equivalent to the mapStateToProps argument to connect conceptually.

You may call useSelector() multiple times within a single function component. Each call to useSelector() creates an individual subscription to the Redux store. Because of the React update batching behavior used in React Redux v7, a dispatched action that causes multiple useSelector()s in the same component to return new values should only result in a single re-render.

:::info

There are potential edge cases with using props in selectors that may cause issues. See the Usage Warnings section of this page for further details.

:::

Equality Comparisons and Updates

When the function component renders, the provided selector function will be called and its result will be returned
from the useSelector() hook. (A cached result may be returned by the hook without re-running the selector if it's the same function reference as on a previous render of the component.)

However, when an action is dispatched to the Redux store, useSelector() only forces a re-render if the selector result
appears to be different than the last result. The default comparison is a strict === reference
comparison. This is different than connect(), which uses shallow equality checks on the results of mapState calls
to determine if re-rendering is needed. This has several implications on how you should use useSelector().

With mapState, all individual fields were returned in a combined object. It didn't matter if the return object was
a new reference or not - connect() just compared the individual fields. With useSelector(), returning a new object
every time will always force a re-render by default. If you want to retrieve multiple values from the store, you can:

  • Call useSelector() multiple times, with each call returning a single field value
  • Use Reselect or a similar library to create a memoized selector that returns multiple values in one object, but
    only returns a new object when one of the values has changed.
  • Use the shallowEqual function from React-Redux as the equalityFn argument to useSelector(), like:
js
import { shallowEqual, useSelector } from 'react-redux'

// Pass it as the second argument directly
const selectedData = useSelector(selectorReturningObject, shallowEqual)

// or pass it as the `equalityFn` field in the options argument
const selectedData = useSelector(selectorReturningObject, {
  equalityFn: shallowEqual,
})
  • Use a custom equality function as the equalityFn argument to useSelector(), like:
js
import { useSelector } from 'react-redux'

// equality function
const customEqual = (oldValue, newValue) => oldValue === newValue

// later
const selectedData = useSelector(selectorReturningObject, customEqual)

The optional comparison function also enables using something like Lodash's _.isEqual() or Immutable.js's comparison capabilities.

`useSelector` Examples

Basic usage:

jsx
import React from 'react'
import { useSelector } from 'react-redux'

export const CounterComponent = () => {
  const counter = useSelector((state) => state.counter)
  return {counter}
}

Using props via closure to determine what to extract:

jsx
import React from 'react'
import { useSelector } from 'react-redux'

export const TodoListItem = (props) => {
  const todo = useSelector((state) => state.todos[props.id])
  return {todo.text}
}

Using memoizing selectors

When using useSelector with an inline selector as shown above, a new instance of the selector is created whenever the component is rendered. This works as long as the selector does not maintain any state. However, memoizing selectors (e.g. created via createSelector from reselect) do have internal state, and therefore care must be taken when using them. Below you can find typical usage scenarios for memoizing selectors.

When the selector does only depend on the state, simply ensure that it is declared outside of the component so that the same selector instance is used for each render:

jsx
import React from 'react'
import { useSelector } from 'react-redux'
import { createSelector } from 'reselect'

const selectNumCompletedTodos = createSelector(
  (state) => state.todos,
  (todos) => todos.filter((todo) => todo.completed).length,
)

export const CompletedTodosCounter = () => {
  const numCompletedTodos = useSelector(selectNumCompletedTodos)
  return {numCompletedTodos}
}

export const App = () => {
  return (
    <>
      Number of completed todos:
      <CompletedTodosCounter />
    </>
  )
}

The same is true if the selector depends on the component's props, but will only ever be used in a single instance of a single component:

jsx
import React from 'react'
import { useSelector } from 'react-redux'
import { createSelector } from 'reselect'

const selectCompletedTodosCount = createSelector(
  (state) => state.todos,
  (_, completed) => completed,
  (todos, completed) =>
    todos.filter((todo) => todo.completed === completed).length,
)

export const CompletedTodosCount = ({ completed }) => {
  const matchingCount = useSelector((state) =>
    selectCompletedTodosCount(state, completed),
  )

  return {matchingCount}
}

export const App = () => {
  return (
    <>
      Number of done todos:
      <CompletedTodosCount completed={true} />
    </>
  )
}

However, when the selector is used in multiple component instances and depends on the component's props, you need to ensure that selector's memoization behavior is properly configured (see here for details).

Development mode checks

useSelector runs some extra checks in development mode to watch for unexpected behavior. These checks do not run in production builds.

:::info

These checks were first added in v8.1.0

:::

Selector result stability

In development, the provided selector function is run an extra time with the same parameter during the first call to useSelector, and warns in the console if the selector returns a different result (based on the equalityFn provided).

This is important, as a selector that returns a different result reference when called again with the same inputs will cause unnecessary rerenders.

ts
// this selector will return a new object reference whenever called,
// which causes the component to rerender after *every* action is dispatched
const { count, user } = useSelector((state) => ({
  count: state.count,
  user: state.user,
}))

If a selector result is suitably stable (or the selector is memoized), it will not return a different result and no warning will be logged.

By default, this will only happen when the selector is first called. You can configure the check in the Provider or at each useSelector call.

tsx title="global setting via context"
{children}
tsx title="individual hook setting"
function Component() {
  const count = useSelector(selectCount, {
    devModeChecks: { stabilityCheck: 'never' },
  })
  // run once (default)
  const user = useSelector(selectUser, {
    devModeChecks: { stabilityCheck: 'once' },
  })
  // ...
}

Identity Function (`state => state`) Check

:::danger Breaking Change!

This was previously referred to as noopCheck.

:::

In development, a check is conducted on the result returned by the selector. It warns in the console if the result is the same as the parameter passed in, i.e. the root state.

A useSelector call returning the entire root state is almost always a mistake, as it means the component will rerender whenever anything in state changes. Selectors should be as granular as possible, like state => state.some.nested.field.

ts no-transpile
// BAD: this selector returns the entire state, meaning that the component will rerender unnecessarily
const { count, user } = useSelector((state) => state)

// GOOD: instead, select only the state you need, calling useSelector as many times as needed
const count = useSelector((state) => state.count.value)
const user = useSelector((state) => state.auth.currentUser)

By default, this will only happen when the selector is first called. You can configure the check in the Provider or at each useSelector call.

tsx title="global setting via context"
{children}
tsx title="individual hook setting"
function Component() {
  const count = useSelector(selectCount, {
    devModeChecks: { identityFunctionCheck: 'never' },
  })
  // run once (default)
  const user = useSelector(selectUser, {
    devModeChecks: { identityFunctionCheck: 'once' },
  })
  // ...
}

Comparisons with `connect`

There are some differences between the selectors passed to useSelector() and a mapState function:

  • The selector may return any value as a result, not just an object.
  • The selector normally should return just a single value, and not an object. If you do return an object or an array, be sure to use a memoized selector to avoid unnecessary re-renders.
  • The selector function does not receive an ownProps argument. However, props can be used through closure (see the examples above) or by using a curried selector.
  • You can use the equalityFn option to customize the comparison behavior

`useDispatch()`

ts
import type { Dispatch } from 'redux'
const dispatch: Dispatch = useDispatch()

This hook returns a reference to the dispatch function from the Redux store. You may use it to dispatch actions as needed.

Examples

jsx
import React from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()

  return (
    
      {value}
       dispatch({ type: 'increment-counter' })}>
        Increment counter
      
    
  )
}

When passing a callback using dispatch to a child component, you may sometimes want to memoize it with useCallback. If the child component is trying to optimize render behavior using React.memo() or similar, this avoids unnecessary rendering of child components due to the changed callback reference.

jsx
import React, { useCallback } from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()
  const incrementCounter = useCallback(
    () => dispatch({ type: 'increment-counter' }),
    [dispatch],
  )

  return (
    
      {value}
      <MyIncrementButton onIncrement={incrementCounter} />
    
  )
}

export const MyIncrementButton = React.memo(({ onIncrement }) => (
  Increment counter
))

:::info

The dispatch function reference will be stable as long as the same store instance is being passed to the ``.
Normally, that store instance never changes in an application.

However, the React hooks lint rules do not know that dispatch should be stable, and will warn that the dispatch variable
should be added to dependency arrays for useEffect and useCallback. The simplest solution is to do just that:

js
export const Todos = () => {
  const dispatch = useDispatch()

  useEffect(() => {
    dispatch(fetchTodos())
    // highlight-start
    // Safe to add dispatch to the dependencies array
  }, [dispatch])
  // highlight-end
}

:::

`useStore()`

ts
import type { Store } from 'redux'
const store: Store = useStore()

This hook returns a reference to the same Redux store that was passed in to the `` component.

This hook should probably not be used frequently. Prefer useSelector() as your primary choice. However, this may be useful for less common scenarios that do require access to the store, such as replacing reducers.

Examples

js
import React from 'react'
import { useStore } from 'react-redux'

export const ExampleComponent = ({ value }) => {
  const store = useStore()

  const onClick = () => {
    // Not _recommended_, but safe
    // This avoids subscribing to the state via `useSelector`
    // Prefer moving this logic into a thunk instead
    const numTodos = store.getState().todos.length
  }

  // EXAMPLE ONLY! Do not do this in a real app.
  // The component will not automatically update if the store state changes
  return {store.getState().todos.length}
}

Custom context

The `` component allows you to specify an alternate context via the context prop. This is useful if you're building a complex reusable component, and you don't want your store to collide with any Redux store your consumers' applications might use.

To access an alternate context via the hooks API, use the hook creator functions:

js
import React from 'react'
import {
  Provider,
  createStoreHook,
  createDispatchHook,
  createSelectorHook,
} from 'react-redux'

const MyContext = React.createContext(null)

// Export your custom hooks if you wish to use them in other files.
export const useStore = createStoreHook(MyContext)
export const useDispatch = createDispatchHook(MyContext)
export const useSelector = createSelectorHook(MyContext)

const myStore = createStore(rootReducer)

export function MyProvider({ children }) {
  return (
    
      {children}
    
  )
}

Usage Warnings

Stale Props and "Zombie Children"

:::info

The React-Redux hooks API has been production-ready since we released it in v7.1.0, and we recommend using the hooks API as the default approach in your components. However, there are a couple of edge cases that can occur, and we're documenting those so that you can be aware of them.

In practice, these are a rare concern - we've received far more comments about these being in the docs than actual reports of these being a real problem in an app.

:::

One of the most difficult aspects of React Redux's implementation is ensuring that if your mapStateToProps function is defined as (state, ownProps), it will be called with the "latest" props every time. Up through version 4, there were recurring bugs reported involving edge case situations, such as errors thrown from a mapState function for a list item whose data had just been deleted.

Starting with version 5, React Redux has attempted to guarantee that consistency with ownProps. In version 7, that is implemented using a custom Subscription class internally in connect(), which forms a nested hierarchy. This ensures that connected components lower in the tree will only receive store update notifications once the nearest connected ancestor has been updated. However, this relies on each connect() instance overriding part of the internal React context, supplying its own unique Subscription instance to form that nesting, and rendering the <ReactReduxContext.Provider> with that new context value.

With hooks, there is no way to render a context provider, which means there's also no nested hierarchy of subscriptions. Because of this, the "stale props" and "zombie child" issues may potentially re-occur in an app that relies on using hooks instead of connect().

Specifically, "stale props" means any case where:

  • a selector function relies on this component's props to extract data
  • a parent component would re-render and pass down new props as a result of an action
  • but this component's selector function executes before this component has had a chance to re-render with those new props

Depending on what props were used and what the current store state is, this may result in incorrect data being returned from the selector, or even an error being thrown.

"Zombie child" refers specifically to the case where:

  • Multiple nested connected components are mounted in a first pass, causing a child component to subscribe to the store before its parent
  • An action is dispatched that deletes data from the store, such as a todo item
  • The parent component would stop rendering that child as a result
  • However, because the child subscribed first, its subscription runs before the parent stops rendering it. When it reads a value from the store based on props, that data no longer exists, and if the extraction logic is not careful, this may result in an error being thrown.

useSelector() tries to deal with this by catching all errors that are thrown when the selector is executed due to a store update (but not when it is executed during rendering). When an error occurs, the component will be forced to render, at which point the selector is executed again. This works as long as the selector is a pure function and you do not depend on the selector throwing errors.

If you prefer to deal with this issue yourself, here are some possible options for avoiding these problems altogether with useSelector():

  • Don't rely on props in your selector function for extracting data
  • In cases where you do rely on props in your selector function and those props may change over time, or the data you're extracting may be based on items that can be deleted, try writing the selector functions defensively. Don't just reach straight into state.todos[props.id].name - read state.todos[props.id] first, and verify that it exists before trying to read todo.name.
  • Because connect adds the necessary Subscription to the context provider and delays evaluating child subscriptions until the connected component has re-rendered, putting a connected component in the component tree just above the component using useSelector will prevent these issues as long as the connected component gets re-rendered due to the same store update as the hooks component.

:::info

For a longer description of these scenarios, see:

:::

Performance

As mentioned earlier, by default useSelector() will do a reference equality comparison of the selected value when running the selector function after an action is dispatched, and will only cause the component to re-render if the selected value changed. However, unlike connect(), useSelector() does not prevent the component from re-rendering due to its parent re-rendering, even if the component's props did not change.

If further performance optimizations are necessary, you may consider wrapping your function component in React.memo():

jsx
const CounterComponent = ({ name }) => {
  const counter = useSelector((state) => state.counter)
  return (
    
      {name}: {counter}
    
  )
}

export const MemoizedCounterComponent = React.memo(CounterComponent)

Hooks Recipes

We've pared down our hooks API from the original alpha release, focusing on a more minimal set of API primitives.
However, you may still wish to use some of the approaches we tried in your own apps. These examples should be ready
to copy and paste into your own codebase.

Recipe: `useActions()`

This hook was in our original alpha release, but removed in v7.1.0-alpha.4, based on Dan Abramov's suggestion.
That suggestion was based on "binding action creators" not being as useful in a hooks-based use case, and causing too
much conceptual overhead and syntactic complexity.

You should probably prefer to call the useDispatch hook in your components to retrieve a reference to dispatch,
and manually call dispatch(someActionCreator()) in callbacks and effects as needed. You may also use the Redux
bindActionCreators function in your own code to bind action creators,
or "manually" bind them like const boundAddTodo = (text) => dispatch(addTodo(text)).

However, if you'd like to still use this hook yourself, here's a copy-pastable version that supports passing in action
creators as a single function, an array, or an object.

js
import { bindActionCreators } from 'redux'
import { useDispatch } from 'react-redux'
import { useMemo } from 'react'

export function useActions(actions, deps) {
  const dispatch = useDispatch()
  return useMemo(
    () => {
      if (Array.isArray(actions)) {
        return actions.map((a) => bindActionCreators(a, dispatch))
      }
      return bindActionCreators(actions, dispatch)
    },
    deps ? [dispatch, ...deps] : [dispatch],
  )
}

Recipe: `useShallowEqualSelector()`

js
import { useSelector, shallowEqual } from 'react-redux'

export function useShallowEqualSelector(selector) {
  return useSelector(selector, shallowEqual)
}

Additional considerations when using hooks

There are some architectural trade-offs to take into consideration when deciding whether to use hooks or not. Mark Erikson summarizes these nicely in his two blog posts Thoughts on React Hooks, Redux, and Separation of Concerns and Hooks, HOCs, and Tradeoffs.


File: docs/api/Provider.md


id: provider title: Provider sidebar_label: Provider hide_title: true

 

`Provider`

Overview

The `` component makes the Redux store available to any nested components that need to access the Redux store.

Since any React component in a React Redux app can be connected to the store, most applications will render a `` at the top level, with the entire app’s component tree inside of it.

The Hooks and connect APIs can then access the provided store instance via React's Context mechanism.

Props

ts
interface ProviderProps<A extends Action<string> = UnknownAction, S = unknown> {
  /**
   * The single Redux store in your application.
   */
  store: Store<S, A>

  /**
   * An optional server state snapshot. Will be used during initial hydration render
   * if available, to ensure that the UI output is consistent with the HTML generated on the server.
   * New in 8.0
   */
  serverState?: S

  /**
   * Optional context to be used internally in react-redux. Use React.createContext()
   * to create a context to be used.
   * If this is used, you'll need to customize `connect` by supplying the same
   * context provided to the Provider.
   * Set the initial value to null, and the hooks will error
   * if this is not overwritten by Provider.
   */
  context?: Context<ReactReduxContextValue<S, A> | null>

  /** Global configuration for the `useSelector` stability check */
  stabilityCheck?: DevModeCheckFrequency

  /** Global configuration for the `useSelector` identity function check */
  identityFunctionCheck?: DevModeCheckFrequency

  /** The top-level React elements in your component tree, such as `<App />` **/
  children: ReactNode
}

Typically, you only need to pass ``.

You may provide a context instance. If you do so, you will need to provide the same context instance to all of your connected components as well. Failure to provide the correct context results in this runtime error:

Invariant Violation

Could not find "store" in the context of "Connect(MyComponent)". Either wrap the root component in a , or pass a custom React context provider to and the corresponding React context consumer to Connect(Todo) in connect options.

React 18 SSR Usage

As of React-Redux v8, `` now accepts a serverState prop for use in SSR hydration scenarios. This is necessary if you are calling hydrateRoot in order to avoid hydration mismatches.

You should pass the entire serialized state from the server as the serverState prop, and React will use this state for the initial hydration render. After that, it will apply any updates from changes that occurred on the client during the setup process.

Examples

Basic Usage

In the example below, the <App /> component is our root-level component. This means it’s at the very top of our component hierarchy.

jsx
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'

import { App } from './App'
import createStore from './createReduxStore'

const store = createStore()

// As of React 18
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  
    <App />
  ,
)

React 18 SSR Hydration

In this example, the client has received HTML rendered by the server, as well as a serialized Redux state attached to window. The serialized state is used to both pre-fill the store's contents, and passed as the serverState prop to ``

tsx title="src/index.ts"
import { hydrateRoot } from 'react-dom/client'
import { configureStore } from '@reduxjs/toolkit'
import { Provider } from 'react-redux'

const preloadedState = window.__PRELOADED_STATE__

const clientStore = configureStore({
  reducer: rootReducer,
  preloadedState,
})

hydrateRoot(
  document.getElementById('root'),
  
    <App />
  ,
)

File: docs/tutorials/connect.md


id: connect title: 'Tutorial: Connect API' hide_title: true sidebar_label: 'Tutorial: Connect API'

 

Tutorial: Using the `connect` API

:::tip

We now recommend using the React-Redux hooks API as the default. However, the connect API still works fine.

This tutorial also shows some older practices we no longer recommend, like separating Redux logic into folders by type. We've kept this tutorial as-is for completeness, but recommend reading through the "Redux Essentials" tutorial and the Redux Style Guide in the Redux docs for our current best practices.

We're working on a new tutorial that will introduce the hooks APIs. Until then, we suggest reading Redux Fundamentals, Part 5: UI and React for a hooks tutorial.

:::

To see how to use React Redux in practice, we’ll show a step-by-step example by creating a todo list app.

A Todo List Example

Jump to

The React UI Components

We have implemented our React UI components as follows:

  • TodoApp is the entry component for our app. It renders the header, the AddTodo, TodoList, and VisibilityFilters components.
  • AddTodo is the component that allows a user to input a todo item and add to the list upon clicking its β€œAdd Todo” button:
    • It uses a controlled input that sets state upon onChange.
    • When the user clicks on the β€œAdd Todo” button, it dispatches the action (that we will provide using React Redux) to add the todo to the store.
  • TodoList is the component that renders the list of todos:
    • It renders the filtered list of todos when one of the VisibilityFilters is selected.
  • Todo is the component that renders a single todo item:
    • It renders the todo content, and shows that a todo is completed by crossing it out.
    • It dispatches the action to toggle the todo's complete status upon onClick.
  • VisibilityFilters renders a simple set of filters: all, completed, and incomplete. Clicking on each one of them filters the todos:
    • It accepts an activeFilter prop from the parent that indicates which filter is currently selected by the user. An active filter is rendered with an underscore.
    • It dispatches the setFilter action to update the selected filter.
  • constants holds the constants data for our app.
  • And finally index renders our app to the DOM.

The Redux Store

The Redux portion of the application has been set up using the patterns recommended in the Redux docs:

  • Store
    • todos: A normalized reducer of todos. It contains a byIds map of all todos and a allIds that contains the list of all ids.
    • visibilityFilters: A simple string all, completed, or incomplete.
  • Action Creators
    • addTodo creates the action to add todos. It takes a single string variable content and returns an ADD_TODO action with payload containing a self-incremented id and content
    • toggleTodo creates the action to toggle todos. It takes a single number variable id and returns a TOGGLE_TODO action with payload containing id only
    • setFilter creates the action to set the app’s active filter. It takes a single string variable filter and returns a SET_FILTER action with payload containing the filter itself
  • Reducers
    • The todos reducer
      • Appends the id to its allIds field and sets the todo within its byIds field upon receiving the ADD_TODO action
      • Toggles the completed field for the todo upon receiving the TOGGLE_TODO action
    • The visibilityFilters reducer sets its slice of store to the new filter it receives from the SET_FILTER action payload
  • Action Types
    • We use a file actionTypes.js to hold the constants of action types to be reused
  • Selectors
    • getTodoList returns the allIds list from the todos store
    • getTodoById finds the todo in the store given by id
    • getTodos is slightly more complex. It takes all the ids from allIds, finds each todo in byIds, and returns the final array of todos
    • getTodosByVisibilityFilter filters the todos according to the visibility filter

You may check out this CodeSandbox for the source code of the UI components and the unconnected Redux store described above.

We will now show how to connect this store to our app using React Redux.

Providing the Store

First we need to make the store available to our app. To do this, we wrap our app with the `` API provided by React Redux.

jsx
// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import TodoApp from './TodoApp'

import { Provider } from 'react-redux'
import store from './redux/store'

// As of React 18
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
  
    <TodoApp />
  ,
)

Notice how our <TodoApp /> is now wrapped with the `` with store passed in as a prop.

Connecting the Components

React Redux provides a connect function for you to read values from the Redux store (and re-read the values when the store updates).

The connect function takes two arguments, both optional:

  • mapStateToProps: called every time the store state changes. It receives the entire store state, and should return an object of data this component needs.

  • mapDispatchToProps: this parameter can either be a function, or an object.

    • If it’s a function, it will be called once on component creation. It will receive dispatch as an argument, and should return an object full of functions that use dispatch to dispatch actions.
    • If it’s an object full of action creators, each action creator will be turned into a prop function that automatically dispatches its action when called. Note: We recommend using this β€œobject shorthand” form.

Normally, you’ll call connect in this way:

js
const mapStateToProps = (state, ownProps) => ({
  // ... computed data from state and optionally ownProps
})

const mapDispatchToProps = {
  // ... normally is an object full of action creators
}

// `connect` returns a new function that accepts the component to wrap:
const connectToStore = connect(mapStateToProps, mapDispatchToProps)
// and that function returns the connected, wrapper component:
const ConnectedComponent = connectToStore(Component)

// We normally do both in one step, like this:
connect(mapStateToProps, mapDispatchToProps)(Component)

Let’s work on <AddTodo /> first. It needs to trigger changes to the store to add new todos. Therefore, it needs to be able to dispatch actions to the store. Here’s how we do it.

Our addTodo action creator looks like this:

js
// redux/actions.js
import { ADD_TODO } from './actionTypes'

let nextTodoId = 0
export const addTodo = (content) => ({
  type: ADD_TODO,
  payload: {
    id: ++nextTodoId,
    content,
  },
})

// ... other actions

By passing it to connect, our component receives it as a prop, and it will automatically dispatch the action when it’s called.

js
// components/AddTodo.js

// ... other imports
import { connect } from 'react-redux'
import { addTodo } from '../redux/actions'

class AddTodo extends React.Component {
  // ... component implementation
}

export default connect(null, { addTodo })(AddTodo)

Notice now that <AddTodo /> is wrapped with a parent component called <Connect(AddTodo) />. Meanwhile, <AddTodo /> now gains one prop: the addTodo action.

We also need to implement the handleAddTodo function to let it dispatch the addTodo action and reset the input

jsx
// components/AddTodo.js

import React from 'react'
import { connect } from 'react-redux'
import { addTodo } from '../redux/actions'

class AddTodo extends React.Component {
  // ...

  handleAddTodo = () => {
    // dispatches actions to add todo
    this.props.addTodo(this.state.input)

    // sets state back to empty string
    this.setState({ input: '' })
  }

  render() {
    return (
      
         this.updateInput(e.target.value)}
          value={this.state.input}
        />
        
          Add Todo
        
      
    )
  }
}

export default connect(null, { addTodo })(AddTodo)

Now our <AddTodo /> is connected to the store. When we add a todo it would dispatch an action to change the store. We are not seeing it in the app because the other components are not connected yet. If you have the Redux DevTools Extension hooked up, you should see the action being dispatched:

You should also see that the store has changed accordingly:

The <TodoList /> component is responsible for rendering the list of todos. Therefore, it needs to read data from the store. We enable it by calling connect with the mapStateToProps parameter, a function describing which part of the data we need from the store.

Our <Todo /> component takes the todo item as props. We have this information from the byIds field of the todos. However, we also need the information from the allIds field of the store indicating which todos and in what order they should be rendered. Our mapStateToProps function may look like this:

js
// components/TodoList.js

// ...other imports
import { connect } from "react-redux";

const TodoList = // ... UI component implementation

const mapStateToProps = state => {
  const { byIds, allIds } = state.todos || {};
  const todos =
    allIds && allIds.length
      ? allIds.map(id => (byIds ? { ...byIds[id], id } : null))
      : null;
  return { todos };
};

export default connect(mapStateToProps)(TodoList);

Luckily we have a selector that does exactly this. We may simply import the selector and use it here.

js
// redux/selectors.js

export const getTodosState = (store) => store.todos

export const getTodoList = (store) =>
  getTodosState(store) ? getTodosState(store).allIds : []

export const getTodoById = (store, id) =>
  getTodosState(store) ? { ...getTodosState(store).byIds[id], id } : {}

export const getTodos = (store) =>
  getTodoList(store).map((id) => getTodoById(store, id))
js
// components/TodoList.js

// ...other imports
import { connect } from "react-redux";
import { getTodos } from "../redux/selectors";

const TodoList = // ... UI component implementation

export default connect(state => ({ todos: getTodos(state) }))(TodoList);

We recommend encapsulating any complex lookups or computations of data in selector functions. In addition, you can further optimize the performance by using Reselect to write β€œmemoized” selectors that can skip unnecessary work. (See the Redux docs page on Computing Derived Data and the blog post Idiomatic Redux: Using Reselect Selectors for Encapsulation and Performance for more information on why and how to use selector functions.)

Now that our <TodoList /> is connected to the store. It should receive the list of todos, map over them, and pass each todo to the <Todo /> component. <Todo /> will in turn render them to the screen. Now try adding a todo. It should come up on our todo list!

We will connect more components. Before we do this, let’s pause and learn a bit more about connect first.

Common ways of calling `connect`

Depending on what kind of components you are working with, there are different ways of calling connect , with the most common ones summarized as below:

Do Not Subscribe to the Store Subscribe to the Store
Do Not Inject Action Creators connect()(Component) connect(mapStateToProps)(Component)
Inject Action Creators connect(null, mapDispatchToProps)(Component) connect(mapStateToProps, mapDispatchToProps)(Component)

Do not subscribe to the store and do not inject action creators

If you call connect without providing any arguments, your component will:

  • not re-render when the store changes
  • receive props.dispatch that you may use to manually dispatch action
js
// ... Component
export default connect()(Component) // Component will receive `dispatch` (just like our <TodoList />!)

Subscribe to the store and do not inject action creators

If you call connect with only mapStateToProps, your component will:

  • subscribe to the values that mapStateToProps extracts from the store, and re-render only when those values have changed
  • receive props.dispatch that you may use to manually dispatch action
js
// ... Component
const mapStateToProps = (state) => state.partOfState
export default connect(mapStateToProps)(Component)

Do not subscribe to the store and inject action creators

If you call connect with only mapDispatchToProps, your component will:

  • not re-render when the store changes
  • receive each of the action creators you inject with mapDispatchToProps as props and automatically dispatch the actions upon being called
js
import { addTodo } from './actionCreators'
// ... Component
export default connect(null, { addTodo })(Component)

Subscribe to the store and inject action creators

If you call connect with both mapStateToProps and mapDispatchToProps, your component will:

  • subscribe to the values that mapStateToProps extracts from the store, and re-render only when those values have changed
  • receive all of the action creators you inject with mapDispatchToProps as props and automatically dispatch the actions upon being called.
js
import * as actionCreators from './actionCreators'
// ... Component
const mapStateToProps = (state) => state.partOfState
export default connect(mapStateToProps, actionCreators)(Component)

These four cases cover the most basic usages of connect. To read more about connect, continue reading our API section that explains it in more detail.


Now let’s connect the rest of our <TodoApp />.

How should we implement the interaction of toggling todos? A keen reader might already have an answer. If you have your environment set up and have followed through up until this point, now is a good time to leave it aside and implement the feature by yourself. There would be no surprise that we connect our <Todo /> to dispatch toggleTodo in a similar way:

js
// components/Todo.js

// ... other imports
import { connect } from "react-redux";
import { toggleTodo } from "../redux/actions";

const Todo = // ... component implementation

export default connect(
  null,
  { toggleTodo }
)(Todo);

Now our todo’s can be toggled complete. We’re almost there!

Finally, let’s implement our VisibilityFilters feature.

The <VisibilityFilters /> component needs to be able to read from the store which filter is currently active, and dispatch actions to the store. Therefore, we need to pass both a mapStateToProps and mapDispatchToProps. The mapStateToProps here can be a simple accessor of the visibilityFilter state. And the mapDispatchToProps will contain the setFilter action creator.

js
// components/VisibilityFilters.js

// ... other imports
import { connect } from "react-redux";
import { setFilter } from "../redux/actions";

const VisibilityFilters = // ... component implementation

const mapStateToProps = state => {
  return { activeFilter: state.visibilityFilter };
};
export default connect(
  mapStateToProps,
  { setFilter }
)(VisibilityFilters);

Meanwhile, we also need to update our <TodoList /> component to filter todos according to the active filter. Previously the mapStateToProps we passed to the <TodoList /> connect function call was simply the selector that selects the whole list of todos. Let’s write another selector to help filtering todos by their status.

js
// redux/selectors.js

// ... other selectors
export const getTodosByVisibilityFilter = (store, visibilityFilter) => {
  const allTodos = getTodos(store)
  switch (visibilityFilter) {
    case VISIBILITY_FILTERS.COMPLETED:
      return allTodos.filter((todo) => todo.completed)
    case VISIBILITY_FILTERS.INCOMPLETE:
      return allTodos.filter((todo) => !todo.completed)
    case VISIBILITY_FILTERS.ALL:
    default:
      return allTodos
  }
}

And connecting to the store with the help of the selector:

js
// components/TodoList.js

// ...

const mapStateToProps = (state) => {
  const { visibilityFilter } = state
  const todos = getTodosByVisibilityFilter(state, visibilityFilter)
  return { todos }
}

export default connect(mapStateToProps)(TodoList)

Now we've finished a very simple example of a todo app with React Redux. All our components are connected! Isn't that nice? πŸŽ‰πŸŽŠ

Get More Help


File: docs/tutorials/quick-start.md


id: quick-start title: Quick Start sidebar_label: Quick Start hide_title: true

 

React Redux Quick Start

:::tip What You'll Learn

  • How to set up and use Redux Toolkit with React Redux

:::

:::info Prerequisites

:::

Introduction

Welcome to the React Redux Quick Start tutorial! This tutorial will briefly introduce you to React Redux and teach you how to start using it correctly.

How to Read This Tutorial

This page will focus on just how to set up a Redux application with Redux Toolkit and the main APIs you'll use. For explanations of what Redux is, how it works, and full examples of how to use Redux Toolkit, see the Redux core docs tutorials.

For this tutorial, we assume that you're using Redux Toolkit and React Redux together, as that is the standard Redux usage pattern. The examples are based on a typical Create-React-App folder structure where all the application code is in a src, but the patterns can be adapted to whatever project or folder setup you're using.

The Redux+JS template for Create-React-App comes with this same project setup already configured.

Usage Summary

Install Redux Toolkit and React Redux

Add the Redux Toolkit and React Redux packages to your project:

sh
npm install @reduxjs/toolkit react-redux

Create a Redux Store

Create a file named src/app/store.js. Import the configureStore API from Redux Toolkit. We'll start by creating an empty Redux store, and exporting it:

js title="app/store.js"
import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
  reducer: {},
})

This creates a Redux store, and also automatically configure the Redux DevTools extension so that you can inspect the store while developing.

Provide the Redux Store to React

Once the store is created, we can make it available to our React components by putting a React Redux around our application in `src/index.js`. Import the Redux store we just created, put a around your <App>, and pass the store as a prop:

js title="index.js"
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
// highlight-start
import store from './app/store'
import { Provider } from 'react-redux'
// highlight-end

// As of React 18
const root = ReactDOM.createRoot(document.getElementById('root'))

root.render(
  // highlight-next-line
  
    <App />
  ,
)

Create a Redux State Slice

Add a new file named src/features/counter/counterSlice.js. In that file, import the createSlice API from Redux Toolkit.

Creating a slice requires a string name to identify the slice, an initial state value, and one or more reducer functions to define how the state can be updated. Once a slice is created, we can export the generated Redux action creators and the reducer function for the whole slice.

Redux requires that we write all state updates immutably, by making copies of data and updating the copies. However, Redux Toolkit's createSlice and createReducer APIs use Immer inside to allow us to write "mutating" update logic that becomes correct immutable updates.

js title="features/counter/counterslice.js"
import { createSlice } from '@reduxjs/toolkit'

export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0,
  },
  reducers: {
    increment: (state) => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. It
      // doesn't actually mutate the state because it uses the Immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes.
      // Also, no return statement is required from these functions.
      state.value += 1
    },
    decrement: (state) => {
      state.value -= 1
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload
    },
  },
})

// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions

export default counterSlice.reducer

Add Slice Reducers to the Store

Next, we need to import the reducer function from the counter slice and add it to our store. By defining a field inside the reducer parameter, we tell the store to use this slice reducer function to handle all updates to that state.

js title="app/store.js"
import { configureStore } from '@reduxjs/toolkit'
// highlight-next-line
import counterReducer from '../features/counter/counterSlice'

export default configureStore({
  reducer: {
    // highlight-next-line
    counter: counterReducer,
  },
})

Use Redux State and Actions in React Components

Now we can use the React Redux hooks to let React components interact with the Redux store. We can read data from the store with useSelector, and dispatch actions using useDispatch. Create a src/features/counter/Counter.js file with a <Counter> component inside, then import that component into App.js and render it inside of <App>.

jsx title="features/counter/counter.js"
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'
import styles from './Counter.module.css'

export function Counter() {
  const count = useSelector((state) => state.counter.value)
  const dispatch = useDispatch()

  return (
    
      
         dispatch(increment())}
        >
          Increment
        
        {count}
         dispatch(decrement())}
        >
          Decrement
        
      
    
  )
}

Now, any time you click the "Increment" and "Decrement buttons:

  • The corresponding Redux action will be dispatched to the store
  • The counter slice reducer will see the actions and update its state
  • The <Counter> component will see the new state value from the store and re-render itself with the new data

What You've Learned

That was a brief overview of how to set up and use Redux Toolkit with React. Recapping the details:

:::tip Summary

  • Create a Redux store with configureStore
    • configureStore accepts a reducer function as a named argument
    • configureStore automatically sets up the store with good default settings
  • Provide the Redux store to the React application components
    • Put a React Redux `` component around your <App />
    • Pass the Redux store as ``
  • Create a Redux "slice" reducer with createSlice
    • Call createSlice with a string name, an initial state, and named reducer functions
    • Reducer functions may "mutate" the state using Immer
    • Export the generated slice reducer and action creators
  • Use the React Redux useSelector/useDispatch hooks in React components
    • Read data from the store with the useSelector hook
    • Get the dispatch function with the useDispatch hook, and dispatch actions as needed

:::

Full Counter App Example

Here's the complete Counter application as a running CodeSandbox:

What's Next?

We recommend going through the "Redux Essentials" and "Redux Fundamentals" tutorials in the Redux core docs, which will give you a complete understanding of how Redux works, what Redux Toolkit and React Redux do, and how to use it correctly.


File: docs/tutorials/typescript.md


id: typescript-quick-start title: TypeScript Quick Start sidebar_label: TypeScript Quick Start hide_title: true

 

React Redux TypeScript Quick Start

:::tip What You'll Learn

  • How to set up and use Redux Toolkit and React Redux with TypeScript

:::

:::info Prerequisites

:::

Introduction

Welcome to the React Redux TypeScript Quick Start tutorial! This tutorial will briefly show how to use TypeScript with Redux Toolkit and React-Redux.

This page focuses on just how to set up the TypeScript aspects. For explanations of what Redux is, how it works, and full examples of how to use Redux, see the Redux core docs tutorials.

React Redux is also written in TypeScript as of version 8, and also includes its own type definitions.

The Redux+TS template for Create-React-App comes with a working example of these patterns already configured.

:::info

The recently updated @types/react@18 major version has changed component definitions to remove having children as a prop by default. This causes errors if you have multiple copies of @types/react in your project. To fix this, tell your package manager to resolve @types/react to a single version. Details:

https://github.com/facebook/react/issues/24304#issuecomment-1094565891

:::

Project Setup

Define Root State and Dispatch Types

Redux Toolkit's configureStore API should not need any additional typings. You will, however, want to extract the RootState type and the Dispatch type so that they can be referenced as needed. Inferring these types from the store itself means that they correctly update as you add more state slices or modify middleware settings.

Since those are types, it's safe to export them directly from your store setup file such as app/store.ts and import them directly into other files.

ts title="app/store.ts"
import { configureStore } from '@reduxjs/toolkit'
// ...

const store = configureStore({
  reducer: {
    posts: postsReducer,
    comments: commentsReducer,
    users: usersReducer,
  },
})

// highlight-start
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
// highlight-end

Define Typed Hooks

While it's possible to import the RootState and AppDispatch types into each component, it's better to create typed versions of the useDispatch and useSelector hooks for usage in your application. This is important for a couple reasons:

  • For useSelector, it saves you the need to type (state: RootState) every time
  • For useDispatch, the default Dispatch type does not know about thunks. In order to correctly dispatch thunks, you need to use the specific customized AppDispatch type from the store that includes the thunk middleware types, and use that with useDispatch. Adding a pre-typed useDispatch hook keeps you from forgetting to import AppDispatch where it's needed.

Since these are actual variables, not types, it's important to define them in a separate file such as app/hooks.ts, not the store setup file. This allows you to import them into any component file that needs to use the hooks, and avoids potential circular import dependency issues.

ts title="app/hooks.ts"
import { useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'

// highlight-start
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
// highlight-end

Application Usage

Define Slice State and Action Types

Each slice file should define a type for its initial state value, so that createSlice can correctly infer the type of state in each case reducer.

All generated actions should be defined using the PayloadAction<T> type from Redux Toolkit, which takes the type of the action.payload field as its generic argument.

You can safely import the RootState type from the store file here. It's a circular import, but the TypeScript compiler can correctly handle that for types. This may be needed for use cases like writing selector functions.

ts title="features/counter/counterslice.ts"
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { RootState } from '../../app/store'

// highlight-start
// Define a type for the slice state
interface CounterState {
  value: number
}

// Define the initial state using that type
const initialState: CounterState = {
  value: 0,
}
// highlight-end

export const counterSlice = createSlice({
  name: 'counter',
  // `createSlice` will infer the state type from the `initialState` argument
  initialState,
  reducers: {
    increment: (state) => {
      state.value += 1
    },
    decrement: (state) => {
      state.value -= 1
    },
    // highlight-start
    // Use the PayloadAction type to declare the contents of `action.payload`
    incrementByAmount: (state, action: PayloadAction<number>) => {
      // highlight-end
      state.value += action.payload
    },
  },
})

export const { increment, decrement, incrementByAmount } = counterSlice.actions

// Other code such as selectors can use the imported `RootState` type
export const selectCount = (state: RootState) => state.counter.value

export default counterSlice.reducer

The generated action creators will be correctly typed to accept a payload argument based on the PayloadAction<T> type you provided for the reducer. For example, incrementByAmount requires a number as its argument.

In some cases, TypeScript may unnecessarily tighten the type of the initial state. If that happens, you can work around it by casting the initial state using as, instead of declaring the type of the variable:

ts
// Workaround: cast state instead of declaring variable type
const initialState = {
  value: 0,
} as CounterState

Use Typed Hooks in Components

In component files, import the pre-typed hooks instead of the standard hooks from React-Redux.

tsx title="features/counter/counter.tsx"
import React, { useState } from 'react'

// highlight-next-line
import { useAppSelector, useAppDispatch } from 'app/hooks'

import { decrement, increment } from './counterSlice'

export function Counter() {
  // highlight-start
  // The `state` arg is correctly typed as `RootState` already
  const count = useAppSelector((state) => state.counter.value)
  const dispatch = useAppDispatch()
  // highlight-end

  // omit rendering logic
}

What's Next?

See the "Usage with TypeScript" page for extended details on how to use Redux Toolkit's APIs with TypeScript.