Redux Toolkit, and integrating React with Redux
Published: 2020-08-17 10:29:15

In this final post of the Redux series I will demonstrate how to use the React-Redux package to make state changes update React UI components. I will also show you how to use the Redux Toolkit package to simplify Redux development. So let's begin.

## React-Redux

Let's begin with React-Redux first. As mentioned in the previous post, you create a React project with Redux support using:

```js
npx create-react-app my-app --template redux
```

This automatically installs React-Redux into your project. There are two key differences in React-Redux projects versus plain Redux projects:

1. `useSelector()` is used instead of `subscribe()` and `getState()`. It returns the value of a state part.
2. `useDispatch()` is used instead of `dispatch()`. It returns a handle to the `dispatch()` method.

In a React-Redux app, you don't access the Redux state directly, you use `useSelector()` and `useDispatch()` within components to read and write Redux state. Whenever Redux state is updated, it will automatically trigger a re-render of the React component that uses that state (via `useSelector()` returning a different value).

State is dispatched the normal way, using the handle to the `dispatch()` method returned by `useDispatch()`:

```js
export function SomeComponent {
  const dispatch = useDispatch()
  //...
  return (
    <button onClick={() => dispatch({type: "SomeAction"})}>Click me</button>
  )
}
```

As for `useSelector()`, that is invoked with a function passed as an argument that returns the relevant part of the state. So this works:

```js
const selectCount = state => state.counter.value
const count = useSelector(selectCount)
```

By intuition, this also works:

```js
const count = useSelector(state => state.counter.value)
```

Finally, you need to pass a Redux store to the main React component so it can propogate that store to child components for them to use. This is done by rendering a `Provider` component above the main `App` component:

```js
import { Provider } from 'react-redux'
import { createStore } from 'redux'

// ...

ReactDOM.render(
  <Provider store={configureStore({ reducer: someReducer })}>
    <App />
  </Provider>,
  document.getElementById('root')
)
// Now the store is accessible from the <App> component and
// its child components
```

### An example React-Redux component

The following component was taken from the Redux.js tutorial and is also available [here](https://redux.js.org/tutorials/essentials/part-2-app-structure#the-react-counter-component). Key parts of the app are indicated with comments.

```js
import React, { useState } from 'react'
import { useSelector, useDispatch } from 'react-redux'
/*
 * These are our action creator functions. They return action objects.
 */
import {
  decrement,
  increment,
  incrementByAmount,
  incrementAsync,
  selectCount
} from './counterSlice'
import styles from './Counter.module.css'

export function Counter() {
  /*
   * `useSelector()` calls `useState()` under the hood causing
   * this component to update if the value returned from
   * `useSelector()` changes.
   */
  const count = useSelector(selectCount)

  /*
   * `useDispatch()` returns the dispatch object from the Redux
   * store variable.
   * Notice in the onClick prop of the <button> tags this
   * dispatch function is called with the return value of the
   * `increment` and `decrement` action creators (an action
   * object)
   */
  const dispatch = useDispatch()
  const [incrementAmount, setIncrementAmount] = useState('2')

  return (
    <div>
      <div className={styles.row}>
        <button
          className={styles.button}
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          +
        </button>
        <span className={styles.value}>{count}</span>
        <button
          className={styles.button}
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          -
        </button>
      </div>
      {/* omit additional rendering output here */}
    </div>
  )
}
```

## Redux Toolkit

It's time to cover the second topic of this post, Redux Toolkit. Redux Toolkit exports `configureStore()` and `createSlice()` functions. If the first one sounds familiar it's because this function exists in Redux as well. But this function is exported from Redux Toolkit so you don't have to import anything from Redux directly. It is used the same way as the Redux `configureStore()`.

As for `createSlice()`, this is the convenience method that generates action creators I was talking about in the previous post. It generates actions in the form `"name"/"reducer"`, where `"name"` is the name of the action creator you give it (some people call "name" a namespace), and `"reducer"` is the name of each reducer. Note that I said each reducer, `createSlice()` accepts several reducers by means of keys in objects. (Please remember that actions are strings that can have any possible value.)

The input object should also contain an `initialState` property that is an object with the initial state values.

`createSlice()` returns what is called a *slice* which is just an action creator that has an `actions` property that is an object of action creators, and a `reducer` property that is the actual reducer function. It is a formal name the Redux community gave it as opposed to a subjective term like "feature" or "a state part".

This is the format of the object that is passed to `createSlice()`:

```js
import { createSlice } from '@reduxjs/toolkit'

export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    // If we don't use a parameter we can omit it like
    // we did to `action`.
    increment: state => {
      return state.value + 1
    },
    decrement: state => {
      return state.value - 1
    },
    incrementByAmount: (state, action) => {
      return state.value + action.payload
    }
  }
})
```

Here's a recap of the properties in the parameter object and returned object:

* Input object:
 - `name`: name of the slice
 - `initialState`: Initial state of the slice
 - `reducers`: an object containing each reducer name and its associated function
* Output object
 - `actions`: action creators returning actions of the form `"name"/"<REDUCER-FUNCTION-NAME>"`. Each action can be accessed by its name, such as `slice.actions.increment`.
 - `reducer`: The reducer function made from combining the reducers passed in the input.

A note about action creators: You can pass a single argument to the action creator to use as the `payload` property. So you type `incrementByAmount(5)` to set the `action.payload` to 5. This works for the other actions to even though I didn't list an action parameter for it, the only reason I didn't list one is because the reducers don't use it.

You might be wondering at this point how can the reducers be combined into one. The answer here is by using a function that Redux exports called `combineReducers()`. This function takes an object as input with each slice as a key and its associated reducer as a value. Here's an example:

```js
const rootReducer = combineReducers({
  users: usersReducer,
  posts: postsReducer,
  comments: commentsReducer
})
```

In fact we can just pass the `reducers` property of the input to this function to get our reducer. In practice though, you don't do this yourself, you let `createSlice()` do this for you.

### And we're done

This concludes the Redux series. I hope this series helped you become familiar with Redux development. If you see any errors in this post, please let me know so I can correct them.