I wanted to share not only how I currently do State Management with React Context but also what I do when I need prevState, If there are any suggestions for improvement let me know.
Hope this helps some of you :)
import React, {
createContext,
useReducer,
useContext,
useEffect,
useRef,
} from 'react';
/* ******* */
/* Reducer */
/* ******* */
function reducer(state, action) {
switch (action.type) {
case 'LOGIN':
return {
...state,
isLoggedIn: true,
};
default:
return state;
}
}
const StateContext = createContext({});
const DispatchContext = createContext({});
const PrevStateContext = createContext({});
const StateContainer = (Context) => {
const context = useContext(Context);
if (context === undefined) {
throw new Error('Context must be used within a Provider');
}
return context;
};
const DispatchContainer = (Context) => {
const context = useContext(Context);
if (context === undefined) {
throw new Error('Context must be used within a Provider');
}
return context;
};
const PrevStateContainer = (Context) => {
const context = useContext(Context);
if (context === undefined) {
throw new Error('Context must be used within a Provider');
}
return context;
};
const AppContextProvider = (props) => {
const { children } = props;
const [state, dispatch] = useReducer(reducer, {
isLoggedIn: false,
});
function usePrevious(value: any) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
let prev = usePrevious(state);
return (
<StateContext.Provider value={state}>
<DispatchContext.Provider value={dispatch}>
<PrevStateContext.Provider value={prev === undefined ? {} : prev}>
{children}
</PrevStateContext.Provider>
</DispatchContext.Provider>
</StateContext.Provider>
);
};
const useAppContext = () => {
return [
StateContainer(StateContext),
DispatchContainer(DispatchContext),
PrevStateContainer(PrevStateContext),
];
};
export { AppContextProvider, useAppContext };
Top comments (4)
I am puzzled by the usePrevious hook, a new instance is created for each render
Thanks, Any recommendations?
I think, creating the function outside of the component (for example: in a folder "hooks") is better.
Yea I wanted somehow to include the code for the hook here so people can see it, but maybe I should have put it outside the Provider which would be the same effect as in a separate folder. Thanks