How to Create a Custom State Management Library With React Hooks and Context API
source link: https://hackernoon.com/how-to-create-a-custom-state-management-library-with-react-hooks-and-context-api
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
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
Catch me on: Github, Twitter, LinkedIn, Medium, Dev.to, Blogspot, Hashnode, Stackblitz
Also published here
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK