How to Create a Custom State Management Library With React Hooks and Context API

Written by devsmitra | Published 2022/11/21
Tech Story Tags: javascript | reactjs | redux | react-hooks | context-api | web-development | front-end-development | beginners-guide | web-monetization

TLDRContext API has been a part of React for a long time, but only in an experimental state. Since React 16.3.0, it’s officially stable and ready to use in production. In this article, I will introduce the React Context API for state management and create a similar solution as Redux without using a third-party library. Without Further Ado, Here Are the Steps: 1** Creating Provider and connect function (same as react-redux connect and Provider) using useReducer, createContext & useContext. Connect component to react app to the above-created Provider.via the TL;DR App

In this article, I will introduce the React Context API for state management and create a similar solution as Redux without using a third-party library.

React Context API

It’s actually not a new idea. Context API has been a part of React for a long time, but only in an experimental state.

Since React 16.3.0, it’s officially stable and ready to use in production.

Without Further Ado, Here Are the Steps

Step: 1 Creating Provider and connect function (same as react-redux connect and Provider) using useReducer, createContext & useContext.

import React, { useReducer, createContext, useContext } from "react";
const initialState = {};
// Create App Context
export const Context = createContext(initialState);
export const Provider = ({ children, reducers}) => {
    const defaultState = reducers(undefined, initialState);
    if (defaultState === undefined) {
       throw new Error("reducer's should not return undefined");
    }
    const [state, dispatch] = useReducer((_state, _action) => {
        return reducers(_state, _action);
    }, defaultState);
    return (
        <Context.Provider value={{ state, dispatch }}>
            {children}
        </Context.Provider>
    );
};
export const useDispatch = () => useContext(Context).dispatch;
export const useSelector = (callback) => {
  const state = { ...useContext(Context).state };
  return callback ? callback(state) : state;
};

Step: 2 Connect react app to the above-created Provider.

const actionMap = {
  INCREMENT: (state, action) => ({ ...state, count: state.count + 1 }),
  DECREMENT: (state, action) => ({ ...state, count: state.count - 1 }),
};

const countReducer = (state = { count: 0 }, action) => {
    const exec = actionMap[action.type];
    return exec ? exec(state, action) : state;
};


const reducers = { countReducer };
const App = () => (
    <Provider reducers={reducers}>
        <Component />
    </Provider>
);

Step: 3 Connect component to react Context.

const Component = () => {
  const dispatch = useDispatch();
  const { count } = useSelector((state) => state.countReducer);
  return (<h3>Context State: {count} </h3>)
}

Live Demo: Here

Bonus Tip

export const combineReducers = (reducers) => {
  const entries = Object.entries(reducers);
  return (state = {}, action) => {
    return entries.reduce((_state, [key, reducer]) => {
      _state[key] = reducer(state[key], action);
      return _state;
    }, {});
  };
};

Thank you for reading 😊

Got any additional questions? please leave a comment.


Must Read If You Haven't

Javascript: No More callbacks, Use Promisify to Convert Callback to Promise

Creating a Custom Hook for Fetching Asynchronous Data: useAsync Hook with Cache

Javascript Promise Methods with polyfill example: A Cheat Sheet for Developer


More Content At

Catch me on: Github, Twitter, LinkedIn, Medium, Dev.to, Blogspot, Hashnode, Stackblitz


Also published here


Written by devsmitra | I'm a technology enthusiast who does web development.
Published by HackerNoon on 2022/11/21