Use Hooks in React Redux

Akhila Ariyachandra - Nov 10 '19 - - Dev Community

PS - This was originally posted in my blog. Check it out if you want learn more about React and JavaScript!
PPS - I got to know about hooks in Redux thanks to Antoine in my previous post.

slashgear_ image

In my previous post I went through setting up Redux in a React app. Since then I learnt about using hooks as an alternative to the connect() Higher Order Component. In this post we will refactor the app we made in the previous post to use the Redux Hooks.

Getting Started

Before we start refactoring let's check out the two hooks we are going to use.

  • useSelector - Allows us to get the state from the Redux store. This hook will be used to replace mapStateToProps in connect().
  • useDispatch - Allows us to dispatch out redux actions. This hook will be used to replace mapDispatchToProps in connect().

Refactoring the Controls Component

First lets remove the props, connect() Higher Order Component and mapStateToProps and mapDispatchToProps.

const Controls = () => {
  return (
    <div>
      <button
        onClick={() => actions.setUserId(user.userId - 1)}
        disabled={user.userId <= 1 || user.isFetchingUser}
      >
        Previous
      </button>

      <button
        onClick={() => actions.setUserId(user.userId + 1)}
        disabled={user.userId >= 10 || user.isFetchingUser}
      >
        Next
      </button>
    </div>
  )
}

export default Controls
Enter fullscreen mode Exit fullscreen mode

Then we need to import the two hooks from react-redux.

import { useSelector, useDispatch } from "react-redux"
Enter fullscreen mode Exit fullscreen mode

To get the redux state, we need to use useSelector. useSelector needs a function as an argument where the redux state is the parameter and the return object is the state we need, similar to mapStateToProps. So use useSelector to declare the user inside the component.

const user = useSelector(state => ({ user: state.user }))
Enter fullscreen mode Exit fullscreen mode

The above line of code can be shortened to the following.

const user = useSelector(state => state.user)
Enter fullscreen mode Exit fullscreen mode

To call the redux actions, we need to declare the dispatch function in the component using the useDispatch hook. After that we can call out redux actions inside the dispatch function like we did in the getUser action.

const dispatch = useDispatch()
Enter fullscreen mode Exit fullscreen mode

Just change all actions to run inside the dispatch function like this.

dispatch(setUserId(user.userId - 1))
Enter fullscreen mode Exit fullscreen mode

In the end the Controls component should look like this.

import React from "react"
import { useSelector, useDispatch } from "react-redux"
import { setUserId } from "../redux/user/actions"

const Controls = () => {
  const user = useSelector(state => state.user)
  const dispatch = useDispatch()

  return (
    <div>
      <button
        onClick={() => dispatch(setUserId(user.userId - 1))}
        disabled={user.userId <= 1 || user.isFetchingUser}
      >
        Previous
      </button>

      <button
        onClick={() => dispatch(setUserId(user.userId + 1))}
        disabled={user.userId >= 10 || user.isFetchingUser}
      >
        Next
      </button>
    </div>
  )
}

export default Controls
Enter fullscreen mode Exit fullscreen mode

Refactoring the Display Component

We need to refactor the Display component the same way we did the Controls component.

  • Remove all the connect() Higher Order Component related code.
  • Import useSelector and useDispatch.
import { useSelector, useDispatch } from "react-redux"
Enter fullscreen mode Exit fullscreen mode
  • Declare the user state using useSelector.
const user = useSelector(state => state.user)
Enter fullscreen mode Exit fullscreen mode
  • Declare the dispatch function using useDispatch.
const dispatch = useDispatch()
Enter fullscreen mode Exit fullscreen mode
  • Change all Redux action to be called inside the dispatch function.
dispatch(getUser(user.userId))
Enter fullscreen mode Exit fullscreen mode

In the end the code for the Display component should look like this.

import React from "react"
import { useSelector, useDispatch } from "react-redux"
import { getUser } from "../redux/user/actions"

const Display = () => {
  const user = useSelector(state => state.user)
  const dispatch = useDispatch()

  React.useEffect(() => {
    dispatch(getUser(user.userId))
  }, [user.userId])

  return (
    <div>
      <table>
        <tbody>
          <tr>
            <td>ID: </td>
            <td>{user.user.id}</td>
          </tr>

          <tr>
            <td>Name: </td>
            <td>{user.user.name}</td>
          </tr>

          <tr>
            <td>Username: </td>
            <td>{user.user.username}</td>
          </tr>

          <tr>
            <td>Email: </td>
            <td>{user.user.email}</td>
          </tr>
        </tbody>
      </table>
    </div>
  )
}

export default Display
Enter fullscreen mode Exit fullscreen mode

Wrap Up

This is a sample of the setup we just did. If you think you missed something, feel free to check out the code.

If you want to learn more about the hooks in react-redux, please check out the official documentation here.

If you found this post helpful please make sure to share it! 😊

. . . . . . . . . . . . . . . . . . . . .