React useContext and CreateContext Tutorial: Update State with a Button Click (Beginner-Friendly)!

React useContext and CreateContext Tutorial: Update State with a Button Click (Beginner-Friendly)!

What are the prerequisites for this project?

  • You should know about React.js

  • You have a basic understanding of how React.js works.

  • You should have an understanding of the useState hook.

  • And finally, react server and client components.

so first you need to understand what is createContext & useContext hook is and How to use it in react.js

This hook is used to manage the global state in react.js/Next.js.

CreateContext Hook

This is used to create a new context object. When you call createContext it returns an object with two properties

  1. Provider.

  2. Consumer.

Provider - This is used to wrap a component that provides the context value.

Consumer - This is used useContext to access the value of the context object.

This is the syntax to create a createContext hook:

"use client";
import React,{createContext,useState,useEffect} from 'react'

let contextName = createContext("null");
export {contextName};

Do not forget to export this object

Our context object is ready now!

Let's write a code to provide this value.


const Provider = ({children}) => {
    const [number ,setNumber]  = useState(0);
    const addNumber = () =>{
        setNumber(number+1);
    }
  return (
    <div>
        <numberContext.Provider value={{number,addNumber}}>
            {children}
        </numberContext.Provider>
    </div>
  )
}

export default CountContextProvider;
export {numberContext};

Actually, both these code snippets are from the same file.

later on, I will explain this code snippet. don't worry!

useContext Hook

usecontext is basically part of the consumer.

We can access the value of the createContext hook in any component with the useContext hook!

You just need to write a single line to access all the values from the provider. let me show you how can you get this value.

import { contextName } from "@/context/contextName";
import React, { useContext } from "react";
let {number ,addNumber} = useContext(numberContext);

You can get as many values as you want with object destructure.

Why use createContext & useContext?

If you are a React developer you heard about prop drilling (Prop drilling itself deserves an article but I will explain in short here).

Prop drilling is a design pattern in React where data is passed down from parent to child. If you want to pass data to component "C". from App.js. You need to pass through the same data first to Comp A, then to Comp B, and finally to Comp C. This is also good for short projects but when your project moves to bigger then it is more difficult to manage state & then useContext and createContext hooks come into the picture!

If your basic is clear let's move to the small project that I created to explain this concept in the project!

My project title is "Number Updater": A fun react project for learning useContext and createContext hook.

Tech Stack

  • NextJs

  • TailwindCSS

Let's dive into a step-by-step guide to this project!

Here is my Project

First, create the next app with this command!

npx create-next-app@latest

Let me show you my folder structure for this project -

Create 3 folders

  1. Component folder inside app folder.

  2. context folder - for creating context.

  3. Providers - To provide context to the whole app.

Let's start with CountContext.jsx Here is the code

// folderName & fileName- /context/CountContext.jsx ;
"use client";
import React, { createContext, useState } from "react";

let numberContext = createContext(null);

const CountContextProvider = ({ children }) => {
  const [number, setNumber] = useState(0);
  const addNumber = () => {
    setNumber(number + 1);
  };
  return (
    <div>
      <numberContext.Provider value={{ number, addNumber }}>
        {children}
      </numberContext.Provider>
    </div>
  );
};

export default CountContextProvider;
export { numberContext };

Let me explain this code

By default, every component is a server component in the next.js. To use hooks in this file we need to use "use client".

This will convert the server component to the client component in next.js.

On 2nd line, we import all the things we require for this file.

3rd and most important we declare a context with createContext and initialize with the value null!

later I wrote a provider function to provide the state(number) to the whole project.

Then I set state with the number and with zero(0) initially and later on I increase the count with setNumber.

addNumber function will increase the number with 1 when I click on the button.

Then I wrap a {children} with the provider component.

The { children } prop is a powerful tool that can be used to create reusable and customizable components in Next.js. It can help you to write more efficient and maintainable code.

value = {{number,addNumber}}

the value prop is used to send the prop to the whole application.

Before that, we need a wrap our layout file with the provider function.

Here is the code for the layout.js

//layout.js
import "./globals.css";
import { Roboto } from "next/font/google";
import CountContextProvider from "@/context/CountContext";
import CountProvider from "@/providers/CountProvider";
const roboto = Roboto({
  weight: "300",
  subsets: ["latin"],
});
export const metadata = {
  title: "Number Updater",
  description: "A fun nextjs project for learning createContext & useContext",
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={roboto.className}>
        <CountProvider>
          <CountContextProvider>{children}</CountContextProvider>
        </CountProvider>
      </body>
    </html>
  );
}

After that, you need to create a provider

//providers/countprovider.jsx 
"use client";
import React, { useContext } from "react";
import { numberContext } from "@/context/CountContext";
const CountProvider = ({ children }) => {
  const number  = useContext(numberContext);
  return <div>{children}</div>;
};

export default CountProvider;

The CountProvider component is a provider component for the numberContext context. Provider components are used to wrap components that need to access a context value. When a component is wrapped in a provider component, it will have access to the context value of the provider component.

and then finally we write a code for our count.jsx

"use client";
import { numberContext } from "@/context/CountContext";
import React, { useContext } from "react";
const Count = () => {
  let {number ,addNumber} = useContext(numberContext);
  return (
    <div className="flex items-center justify-between py-2 px-8 rounded-md bg-slate-800 text-white flex-col mx-6 my-10 gap-5 lg:w-96 lg:h-auto place-items-center">
      <p className="font-semibold py-2 px-2 text-lg">Count Number is {number}</p>
      <button onClick={addNumber} className="py-2 px-10 bg-green-700 rounded-md">Click</button>
    </div>
  );
};

export default Count;

We destructure the value {number,addNumber} from useContext hook and then I use it in the main component.

and the final result is here!

The resource I follow for this project

  1. React.dev

  2. Youtube(Thapa Technical).

Thank you for reading