DEV Community

vinodchauhan7
vinodchauhan7

Posted on

Converting React-Redux Class Components to Hooks

With the advancement of day-to-day technology, React-Redux had also released hooks with its 7.1.0 version. So this means we also need to update ourselves with latest react practices.

React-Hooks

React Hooks helps us to write less code for the same functionality which we write earlier with class components. If you are new to React-hooks please have a look on my recent article on hooks.

In this post, we will convert our simple react-redux application which is currently using class based component approach into hooks with redux.

Here is basic codesandbox

View of Counter Class-Component

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

class Counter extends Component {
  render() {
    return (
      <div>
        <h3>Count : {this.props.data.count}</h3>
        <p>
          <button
            onClick={() => this.props.dispatch({ type: "INC", value: 1 })}
          >
            INCREMENT
          </button>

          <br />
          <br />

          <button
            onClick={() => this.props.dispatch({ type: "DEC", value: 1 })}
          >
            DECREMENT
          </button>
        </p>
      </div>
    ); //return ends here
  } //render ends here
}

const mapsStateToProps = state => {
  return {
    data: state
  };
};

export default connect(mapsStateToProps)(Counter);

Now lets go step by step :

1) Convert 'Counter' class component to function component.

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

const Counter = props => {
  return (
    <div>
      <h3>Count : {props.data.count}</h3>
      <p>
        <button onClick={() => props.dispatch({ type: "INC", value: 1 })}>
          INCREMENT
        </button>

        <br />
        <br />

        <button onClick={() => props.dispatch({ type: "DEC", value: 1 })}>
          DECREMENT
        </button>
      </p>
    </div>
  ); //return ends here
};

const mapsStateToProps = state => {
  return {
    data: state
  };
};

export default connect(mapsStateToProps)(Counter);

In above conversion, We have just made functional component and its already code seems very less.

2) Currently we are fetching data from our stores via the mapStateToProps() and
then wrapping our functional component with in connect HOC.

useSelector

useSelector hook help us to read state from stores. We need to import 'useSelector' from 'react-redux'

Import

import { connect, useSelector } from "react-redux";

ReadStatefromStoreViaHook

let data = useSelector(state => state);

UseStateInComponent

<h3>Count : {data.count}</h3>

NoMapsStateToProps

export default connect()(Counter);

3) Till now we successfully read state via useSelector from our store & update our component, now we will look into 'useDispatch' hook to dispatch actions to our store.

useDispatch :

useDispatch help us to dispatch action from component to store.

Import

import { useSelector, useDispatch } from "react-redux";

MakeObject

 const dispatch = useDispatch();

UpdateButtonOnClickEvent

<p>
        <button onClick={() => dispatch({ type: "INC", value: 1 })}>
          INCREMENT
        </button>

        <br />
        <br />

        <button onClick={() => dispatch({ type: "DEC", value: 1 })}>
          DECREMENT
        </button>
      </p>

NoHOC_Connect

export default Counter;

Congratulation

You have successfully converted to functional component using react-redux hooks.

Reducer

const initialState = {
  count: 0
};

const reducer = (state = initialState, action) => {
  let newState = { ...state };
  switch (action.type) {
    case "INC":
      newState.count = newState.count + action.value;
      state = { ...newState };
      return newState;
    case "DEC":
      newState.count = newState.count - action.value;
      state = { ...newState };
      return newState;
    default:
      return newState;
  }
};

export default reducer;

Index.js

import React from "react";
import ReactDOM from "react-dom";
import reducer from "./store/reducer";
import { Provider } from "react-redux";
import { createStore } from "redux";
import Counter from "./counter";

import "./styles.css";

const store = createStore(reducer);

function App() {
  return (
    <div className="App">
      <Counter />
    </div>
  );
}

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

If anyone having issue in conversion, please let me know. I will be happy to help you guys.

Top comments (0)