React Context Custom Hook | The only Global State you’ll ever need

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 ha…


This content originally appeared on DEV Community and was authored by ?Mervyn

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!


This content originally appeared on DEV Community and was authored by ?Mervyn


Print Share Comment Cite Upload Translate
APA
?Mervyn | Sciencx (2022-10-02T13:13:52+00:00) » React Context Custom Hook | The only Global State you’ll ever need. Retrieved from https://www.scien.cx/2021/05/01/react-context-custom-hook-the-only-global-state-youll-ever-need/.
MLA
" » React Context Custom Hook | The only Global State you’ll ever need." ?Mervyn | Sciencx - Saturday May 1, 2021, https://www.scien.cx/2021/05/01/react-context-custom-hook-the-only-global-state-youll-ever-need/
HARVARD
?Mervyn | Sciencx Saturday May 1, 2021 » React Context Custom Hook | The only Global State you’ll ever need., viewed 2022-10-02T13:13:52+00:00,<https://www.scien.cx/2021/05/01/react-context-custom-hook-the-only-global-state-youll-ever-need/>
VANCOUVER
?Mervyn | Sciencx - » React Context Custom Hook | The only Global State you’ll ever need. [Internet]. [Accessed 2022-10-02T13:13:52+00:00]. Available from: https://www.scien.cx/2021/05/01/react-context-custom-hook-the-only-global-state-youll-ever-need/
CHICAGO
" » React Context Custom Hook | The only Global State you’ll ever need." ?Mervyn | Sciencx - Accessed 2022-10-02T13:13:52+00:00. https://www.scien.cx/2021/05/01/react-context-custom-hook-the-only-global-state-youll-ever-need/
IEEE
" » React Context Custom Hook | The only Global State you’ll ever need." ?Mervyn | Sciencx [Online]. Available: https://www.scien.cx/2021/05/01/react-context-custom-hook-the-only-global-state-youll-ever-need/. [Accessed: 2022-10-02T13:13:52+00:00]
rf:citation
» React Context Custom Hook | The only Global State you’ll ever need | ?Mervyn | Sciencx | https://www.scien.cx/2021/05/01/react-context-custom-hook-the-only-global-state-youll-ever-need/ | 2022-10-02T13:13:52+00:00
https://github.com/addpipe/simple-recorderjs-demo