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;
};
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>
);
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;
}, {});
};
};
Got any questions or additional? please leave a comment.
What is Next
React best practices and patterns to reduce code
Rahul Sharma γ» Mar 15 '22
How to solve REST API routing problem with decorators?
Rahul Sharma γ» Mar 23 '22
Catch me on
Youtube Github LinkedIn Medium Stackblitz Hashnode HackerNoon
Top comments (6)
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
Its very helpful. Thanks.
Hey, nice article. You can add syntax highlights as well.
read here
github.com/adam-p/markdown-here/wi...
Thank you so much, It's really helpful π
Great article mate!
Thanks π
Coming up with few more like this.