DEV Community

Rahul Sharma
Rahul Sharma

Posted on • Updated on

3 steps to create custom state management library with React Hooks and Context API

3 steps to create custom state management library with React Hooks and Context API
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 as 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;
};
Enter fullscreen mode Exit fullscreen mode

Step: 2 Connect react app to 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>
);
Enter fullscreen mode Exit fullscreen mode

Step: 3 Connect component to react Context

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

3 steps to create custom state management library with React Hooks and Context API

Live Demo: Here


3 steps to create custom state management library with React Hooks and Context API

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;
    }, {});
  };
};
Enter fullscreen mode Exit fullscreen mode

Got any questions or additional? please leave a comment.


What is Next

Catch me on

Youtube Github LinkedIn Medium Stackblitz Hashnode HackerNoon

Top comments (6)

Collapse
 
dkumar431 profile image
Deepak kumar padhy

This pattern is Okay if you are building a small scale application, but if you are developing a enterprise level application, I would surely recommend to stay away from this approach.
With this approach a lot of components will unnecessarily rerender (Note: There are ways to avoid it but it's bit complicated.) So if you are using large scale application always use some proven libraries like redux-toolkit or zustand etc

Collapse
 
deepaksinghkushwah profile image
Deepak Singh Kushwah

Its very helpful. Thanks.

Collapse
 
biomathcode profile image
Pratik sharma

Hey, nice article. You can add syntax highlights as well.

read here
github.com/adam-p/markdown-here/wi...

Collapse
 
devsmitra profile image
Rahul Sharma

Thank you so much, It's really helpful 😊

Collapse
 
marcomoscatelli profile image
Marco Moscatelli

Great article mate!

Collapse
 
devsmitra profile image
Rahul Sharma • Edited

Thanks 😊

Coming up with few more like this.