With a bunch of state management library out there. All you need is something you already have. React Context with the help of hooks can be your go-to for smaller project.
Making custom hooks is one of React concept you will need to know.
Lately I have been using a custom hook to handle my global state for ease of use.
Custom Hook
Here is an example.
Always name your custom hook starting with use
, so react will treat it as a hook.
useCtxDark.jsx
import { useState, createContext, useContext, useMemo } from 'react'
const darkContext = createContext(null)
export const DarkProvider = ({ children }) => {
const [dark, setDark] = useState(false)
const darkValue = useMemo(() => [dark, setDark], [dark])
return
<darkContext.Provider value={darkValue}>
{children}
</darkContext.Provider>
}
export default function useCtxDark() {
return useContext(darkContext)
}
In our custom hook we define our createContext()
, and a state either useState
or useReducer
where we store data. Then we store that data to memoize it in useMemo
to reduce re-renders.
Notice that we have 2 exports. A named export which is gonna be our Provider that wraps our app and a default export which is our hook that is used to get and set our data.
Now we setup it up by wrapping our app with our Context Provider
App.jsx
import { DarkProvider } from '@/hooks/useCtxDark'
export default function App() {
return (
// Wrapper
<DarkProvider>
<Nav />
<Pages />
</DarkProvider>
)
}
Then we us it like a hook and have access to the global state where ever we call this hook.
DarkToggle.jsx
import useCtxDark from '@/hooks/useCtxNav'
const Nav = () => {
const [dark, setDark] = useCtxDark()
return <input type='checkbox' onChange={() => setDark(!dark)} />
}
Here is an example using useReducer
import { useReducer, useContext, createContext, useMemo } from 'react'
const globalContext = createContext(null)
const initialState = {
todo: []
}
const reducer = (state, action) => {
switch (action.type) {
case "ADD":
return { todo: [...state.todo, action.payload] };
case "DELETE":
const filltered = state.todos.filter((x) => x.id !== action.payload)
return {
...state,
todos: [...filltered],
}
default:
return state;
}
}
export const GlobalProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState)
const stateValue = useMemo(() => [state, dispatch], [state])
return
<globalContext.Provider value={stateValue}>
{children}
</globalContext.Provider>
}
export default function useCtxDark() {
return useContext(globalContext)
}
And you can make multiples of these together when you need more!
Providers.jsx
import { DarkProvider } from '@/hooks/useCtxDark'
import { NavProvider } from '@/hooks/useCtxNav'
const Providers = ({children}) => {
return(
<DarkProvider>
<NavProvider>
{children}
</NavProvider>
</DarkProvider>
)
}
Multi-Context
Another version, where you make a separate context for your state and dispatch.
useStore.jsx
import { useState, createContext, useContext, useMemo } from 'react'
const storeContext = createContext(null)
const dispatchContext = createContext(null)
export const StoreProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState)
return
<dispatchContext.Provider value={dispatch}>
<storeContext.Provider value={state}>
{children}
</storeContext.Provider>
</darkContext.Provider>
}
export function useCtxStore() {
return useContext(storeContext)
}
export function useCtxDispatch() {
return useContext(dispatchContext)
}
Then import just the hook for store
import {useCtxStore, useCtxDispatch} from './useStore'
const Component = () => {
const {todos} = useCtxStore()
const dispatch = useCtxDispatch()
const clickHandler = (id) => {
dispatch({type: '', payload: id})
}
return(
<ul>
{todos.map((item) =>
<li key={item.id} onClick={() => clickHandler(item.id)}>
{item.name}
</li>
)}
</ul>
)
}
Here is a live example with all the above hooks
If your planning to do get some asynchronous data. I do recommend that you use a library for data fetching like React Query or SWR for better UX and Dev Exp.
A perfect pair to React Context for a light weight State Management for both Global and Synchronous State!
Top comments (0)