Learn using react hooks with redux

Learn using react hooks with redux

In this post we will look into learn using react hooks with redux and how to do it easily. After reading this post you will be able to handle redux state and dispatching events very easily with react hooks inside functional components of react. I assume you have our redux store ready and you have done all the pre-requisites which are needed to start with redux such as creating a store, wrapping app inside store provider. In this post I will just explain how to use the existing store with react hooks.

What is Redux And why you should use it?

Redux is state management for react applications. In simple words, we can use it for saving state in the global state so that we can easily have it available on every component throughout the applications checkout redux documentation. Redux is a single source of truth when it comes to states in redux connected applications.

I find it very essential for any application which deals with more than 2-3 functionalities or modules. As the application grows the complexity of the application also grows and if you keep all the state in component’s local state whether it Stateful component or Stateless component with react hooks to store state. It will be complex to pass state to other components which is not a sibling. Then you only have 2 options to pass props which are:

  1. Pass props as routing props
  2. Store it in local/session storage and fetch in the component you need it.
Both of the above solutions are not that feasible or not in good practice. You can not store data in local/session storage every time nor you can send it on URL if the data is sensitive. 

Here Redux comes handy to store data and receive it anywhere in the application. It is a subscription type of methodology. You connect your component with the Redux store and whenever any value is updated, all the connected components will receive the updated value instantly.

How to connect react hooks with redux?

Connecting react hooks with redux store is the same as we connect to the stateful component or class component. We require a connect method from the react-redux library. 
import React from "react";
import { connect } from "react-redux";

import { addCounterValue, resetCounter } from "./CounterActions";

const Counter = ({ counter, addCounterValue, resetCounter }) => {
    ......
};

const mapStateToProps = ({ counterReducer }) => {
    return {
        counter: counterReducer.counter
    };
};

export default connect(mapStateToProps,{ addCounterValue, resetCounter })(Counter);

In the above code snippet you can see I have a functional component named Counter which handles mouse click counters. It has a counter prop passed to the component which is called from mapStateToProps function which needs to call the values from redux state and map it to components props and available to props and also there are two functions addCounterValue and resetCounter which is actions for my counter to manipulate the values in redux store and that has been passed as a second parameter to connect function and it gets dispatch function attached to the function which you can see below

import {
  ADD_COUNTER_VALUE,
  RESET_COUNTER
} from "library/common/constants/StoreConstants";

export const addCounterValue = () => (dispatch, getState) => {
    const counter = getState().counterReducer.counter;
    dispatch({
        type: ADD_COUNTER_VALUE,
        payload: counter + 1
    });
};

export const resetCounter = () => dispatch => {
    dispatch({
        type: RESET_COUNTER
    });
};

Both of my actions have dispatch functions that are needed to dispatch an action. I prefer to dispatch action from my functions not from mapDispatchToProps which can be handled in the component which keeps my dispatching clean. Let's look into my reducer also.

import {
  ADD_COUNTER_VALUE,
  RESET_COUNTER
} from "library/common/constants/StoreConstants";

const initialState = {
    counter: 0
};

const CounterReducer = (state = initialState, action) => {
    switch (action.type) {
        case ADD_COUNTER_VALUE:
            return {
            ...state,
            counter: action.payload
            };
        case RESET_COUNTER:
            return {
            ...initialState
            };
        default:
            return state;
    }
};

export default CounterReducer;

So in my reducer I've counter as 0 and it is manipulated every time an action is dispatched whether it is to increase a counter or to reset the counter and it is received by subscribed component and update the DOM with the latest value received. Now let's check the component rendering logic and calling the action functions.

import React from "react";
import { connect } from "react-redux";

import { addCounterValue, resetCounter } from "./CounterActions";

const Counter = ({ counter, addCounterValue, resetCounter }) => {
    const handleAddCounter = e => {
        e.preventDefault();
        addCounterValue();
    };

    const handleResetCounter = e => {
        e.preventDefault();
        resetCounter();
    };

    return (
        <div>
        <h3>Counter: {counter}</h3>
        <button onClick={handleAddCounter}>Increase Counter</button>
        <button onClick={handleResetCounter}>Reset Counter</button>
        </div>
    );
};

const mapStateToProps = ({ counterReducer }) => {
    return {
        counter: counterReducer.counter
    };
};

export default connect(mapStateToProps,{ addCounterValue, resetCounter })(Counter);

Notice here I have passed the actions to the components as props and called them inside my handle event function and the counter value is updated every time I click either of the buttons and updated value is rendered on the screen.

So this way you can handle redux dispatching actions and getting the updated values from redux with react hooks.