DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Cover image for How I use Context and Hooks to manage State in React JS
Shadman Shakib
Shadman Shakib

Posted on

How I use Context and Hooks to manage State in React JS

Managing state is a big part of front-end development in this age of JavaScript frameworks. There are a lot of options to manage state in React JS. May be most common using Redux. But using Redux for a small application may not be ideal. React has a built-in context API and hooks to manage state. In this article I will try to explain how I manage state with Context API and hooks.

Context Overview

According to official React documentation, Context provides a way to share values between components without having to explicitly pass a prop through the level of the tree. Basically, what Context does is make state available anywhere from the application without passing it through props.

Creating Context

You can create context simply by calling createContext() .

const UIContext=React.createContext(initialState)
Enter fullscreen mode Exit fullscreen mode

This creates a context object. When React renders a component that subscribes to this Context object it will read the current context value form the closest matching Provider above it in the tree. The initial state is only used when a component dose not have a matching Provider above it in the tree. For example passing the toggle menu state as initial state.

import React from "react"
//setting up the initial state
const initialState={
isMenuOpen:false;
}
//creating a context
const UIContext=React.createContext(initialState)
Enter fullscreen mode Exit fullscreen mode

Setting up the Provider function

Every context object comes with a Provider component that allows consuming components to subscribe to context changes. In order to get access to the state one component must be placed inside the provider. I have created a Provider function to accomplish this task.

export const UIProvider=(props)=>{
return <UIContext.Provider value={} {...props}/>
}
Enter fullscreen mode Exit fullscreen mode

Using Hooks to change the state

Hooks are functions that let you β€œhook into” React state and life cycle features from functional components. Before introductions of hooks in React 16.8 class-based components were mandatory for any projects that require states, life-cycle methods, and many other important functionalities.
The useReducer hook is used to handle complex logic. The hook takes a reducer as an argument and can optionally take the initial state and an init function as arguments. The useReducer It’s return states and a function which you can call to dispatch action. Writing Reducer functions for your context

const [state, dispatch]=React.useReducer(reducer, initialState ,init)
Enter fullscreen mode Exit fullscreen mode

Dispatching action to change state

We can dispatch functions by calling the dispatch function we get from the useReducer hook. Here we specify the type of action we wanna dispatch.
The useCallback hook will return a memorized version of the callback that only changes if one of the dependencies has changed. This is used to prevent unnecessary renders.

//useReducer Hook
const [state,dispatch]=React.useReducer(uiReducer,initialState)
//dispatching action
const toggleMenu=React.useCallback(()=>dispatch({type:"TOGGLE_MENU"}),[dispatch])
Enter fullscreen mode Exit fullscreen mode

Passing the value to Context Provider

Now we need to pass our state and actions in the UIContext provider. Here, I have used the useMemo hook to memorize the value.

import React from "react"

export const UIProvider=(props)=>{
const [state,dispatch]=React.useReducer(uiReducer,initialState)
//dispatching action
const toggleMenu=React.useCallback(()=>dispatch({type:"TOGGLE_MENU"}),[dispatch])

const value=useMemo(()=>({...state,}),[state])
return <UIContext.Provider value={value} {...props}/>
}
Enter fullscreen mode Exit fullscreen mode

Putting the App inside provider function

This will make the state available to all the components of the app. For this we need to pass the entire app component inside the UIProvider.

//index.js
import {UIProvider} from "./UIContext"
export default function Index (){
return (
<UIProvider>
    <App/>
</UIProvider>
  )
}
Enter fullscreen mode Exit fullscreen mode

Building a custom hook to consume the context

Most of the time I create a custom hook to consume context.
HereuseContext hook is used to consume Context. We need to pass the name of the Context which we wanna use in order to consume the context.

//useUI.tsx
import React from "react"
import UIContext from "./UIContext"
const useUI=()=>{
const context=React.useContext(UIContext)
return context;
}
Enter fullscreen mode Exit fullscreen mode

Using useUI hook

Now it’s time to use the useUI hook. Simply, import it and call it inside the functional component you want to use. Here we will get the value isMenuOpen and toggleMenu function.

import useUI from "./hooks/useUI"
const {isMenuOpen, toggleMenu}=useUI()
export const App=()=>{
return (
<div>
<button onClick={toggleMenu}>Click </button>
<p>{isMenuOpen? "Open" : "Close"} </p>
</div>
)
}
Enter fullscreen mode Exit fullscreen mode

Thank you for reading the article. If I can help you some way let me know. I will do my best.

Top comments (0)

We are hiring! Do you want to be our Senior Platform Engineer? Are you capable of chipping in across sysadmin, ops, and site reliability work, while supporting the open source stack that runs DEV and other communities?

This role might just be for you!

Apply now