DEV Community

Buddy Agyin 🦁
Buddy Agyin 🦁

Posted on

Start Using Redux Hooks in Your Projects

Redux hooks have been around for quite some time now so why aren't you using them in your projects? Maybe you're just too attached to connect(), mapStateToProps and mapDispatchToProps. Maybe you just haven't taken the time to research the Redux hooks and how to utilize them in your projects. Or maybe, you just find them to be a little bit confusing.

Don't worry because I too was just a little too comfortable with using the standard methods for Redux. But once I decided to jump in and actually implement the Redux hooks, I haven't looked back.

I'll help walk you through some examples of how you can replace mapStateToProps and mapDispatchToProps with the easy to use useSelector and useDispatch hooks.

Let's take a look:

// ../reducers/ui.js

import * as types from '../actions/types'

export const ui = (state=initialState, {type, payload}) => {
    switch (type) {
        case types.SET_EXERCISE_VISIBILTY:
            console.log('action', payload)
            return {
                exerciseModal: payload
            }
        default:
            return state
    }
}

const initialState = {
    exerciseModal: false
}

// ../reducers/exercises.js

import * as types from '../actions/types'
import { exercises as initialState } from '../initialState.js'

export const exercises = (state=initialState, {type, payload}) => {
    switch (type) {
        case types.FILTER_EXERCISES:
            console.log(payload)
            const newArray = initialState.filter(item => item.name.toLowerCase().includes(payload.toLowerCase()))
            return [...newArray]
            break;
        default:
            break;
    }
    return state
}

// ../reducers/index.js

import { ui } from './ui.js'
import { exercises } from './exercises.js'
import { combineReducers } from 'redux'

export default combineReducers({
    exercises,
    ui
})

// ../store/store.js

import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from '../reducers'

export const store = createStore(rootReducer, applyMiddleware(thunk))

Enter fullscreen mode Exit fullscreen mode

What I did here was created two separate reducer files. I imported them all into a single file, ../reducers/index.js and utilized the Redux hook combineReducers to combine them into a single root reducer.

In the ../store/store.js file, I went ahead and created our Redux store with my root reducer and the thunk middleware to allow me to perform my dispatches asynchronously.

Now let's create our actions:


// ../actions/types.js

export const SET_EXERCISE_VISIBILTY = 'SET_EXERCISE_VISIBILTY'
export const FILTER_EXERCISES = 'FILTER_EXERCISES'

// ../actions/actions.js

import * as types from './types.js'

export const setExerciseModalVisibilty = (visible) => dispatch =>  {
    dispatch({type: types.SET_EXERCISE_VISIBILTY, payload: visible})
}

export const filterExercises = (filter) => dispatch => {
    console.log(filter)
    dispatch({type: types.FILTER_EXERCISES, payload: filter})
}
Enter fullscreen mode Exit fullscreen mode

Here I created two separate files, one to store our actions and the other to store our types.

Now that we have those set up we can head on over to our index.js file to set up our Provider

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
import { Provider } from 'react-redux';
import { store } from './store/store.js'

ReactDOM.render(
<Provider store={store}>
    <App />
</Provider>
, document.getElementById('root'));

Enter fullscreen mode Exit fullscreen mode

Alright, let's start using our reducers inside of our components now.

I'll show you how it would look utilizing mapStateToProps, mapDispatchToProps and connect before refactoring it to utilize useSelector and useDispatch


// using mapStateToProps and connect

import React from 'react'
import { TopBar } from './TopBar.js'
import { setExerciseModalVisibilty } from '../actions/actions'
import { connect } from 'react-redux'

const CurrentWorkout = (props) => {
    return(
        <>
            <TopBar style={styles.topBar}>
                <h2>
                    Current Workout
                </h2>
            </TopBar>
            <div>
                <p>
                    add some exercises
                </p>
                <button onClick={() => props.setExerciseVisibilityModal(!props.visible)}>
                        +
                </button>
            </div>
            {props.visible && props.exercises.map(exercise => (<h3>{exercise.name}</h3>))}
        </>
    )
}

const mapStateToProps = ({ui, exercises}) => {
   return {
      visible: ui.exerciseModal,
      exercises: exercises
 }
}

const mapDispatchToProps = {
  setExerciseModalVisibility
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(CurrentWorkout)


// using Redux hooks

import React from 'react'
import { TopBar } from './TopBar.js'
import { setExerciseModalVisibilty } from '../actions/actions'
import { useDispatch, useSelector } from 'react-redux'

const CurrentWorkout = (props) => {
    const [visible, exercises] = useSelector(({ui, exercise}) => [ui.exerciseModal, exercises])
    const dispatch = useDispatch()

    return(
        <>
            <TopBar style={styles.topBar}>
                <h2>
                    Current Workout
                </h2>
            </TopBar>
            <div>
                <p>
                    add some exercises
                </p>
                <button onClick={() => dispatch(setExerciseModalVisibilty(!visible))}>
                        +
                </button>
            </div>
            {visible && exercises.map(exercise => (<h3>{exercise.name}</h3>))}
        </>
    )
}

export default CurrentWorkout
Enter fullscreen mode Exit fullscreen mode

As you can see, by utilizing useSelector we can return an array with our wanted state directly inside of our component.

Similarly, we can use useDispatch to create a reference to our dispatch functions inside of our Redux store. We can then pass our action inside of that dispatch reference.

Next time, I'll show you how you can implement the Redux Toolkit into your projects.

For a deeper dive into Redux hooks, be sure to check out the official docs here

Top comments (0)