How to use React Context in Next JS 14

Introduction

Today, we are going to use React Context in NextJS 14. If you want to use React Context in your NextJS web app, then you are at the right place.

We'll set up the latest NextJs project and implement state control through React Context.

Why Use React Context in NextJS?

React Context is a powerful method for state management in your app. Let's see why you should use React Context in NextJS. Here are some reasons:

  • React Context helps manage the state of your app across several components. It helps in eliminating the problem of Prop drilling.

  • Data fetched through APIs (like User Data, Authentication,...) could be kept as 'global' in the React Context.

  • It is a built-in feature in React JS. You don't need any other dependencies to use it in NextJS.

Setting up NextJS 14 Project

Now let's set up the latest NextJs project in your local environment. First, you should have NodeJS (with NPM) installed in your system. If you don't have one, you can install it from here.

Run the following command on the terminal to start a new NextJS project:

npx create-next-app@latest

This will prompt you for the Project details, fill it as shown below:

Now after some time, a new NextJS project will be made. It should look like this:

Finally, the project setup is complete. Now we can start using React Context in our app.

Creating Context and Context State

Now let's create the custom React Context for your states. Here you would have to create two main things:

  • Context Provider: We will be creating a context provider function to wrap our main app around it. It helps in making the app available to all the components (children).

  • UseContext: You have to create a custom useContext function, which will take a callback as the default useContext function from 'react'.

//app/Context/NameContext.tsx

'use client';

import { createContext, useContext, useState } from "react";

const nameContext = createContext({});

interface Props {
    children: React.ReactNode
}

export const NameContextProvider = ({ children }: Props) => {
    const [Name, setName] = useState<string>("Ashish");

    return (
        <nameContext.Provider value={{ Name }}>
            {children}
        </nameContext.Provider>
    )
}

export const useNameContext = () => useContext(nameContext);

Wrapping Context Provider to Root Layout

Now, we have created the context and states that can be passed to our app. Here, we will be wrapping the context around the root layout of our app.

It will help in making our states available to all the components of Root.

//app/layout.tsx

import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { NameContextProvider } from './Context/NameContext'
import './globals.css'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <NameContextProvider>
          {children}
        </NameContextProvider>
      </body>
    </html>
  )
}

Using React Context in our app

Now, import our custom useContext function accepting callback. You can directly destructure the required states or functions.

useContext can be used in any component (corresponding to '/' root) and respective states are accessible.

'use client';

import { useNameContext } from "./Context/NameContext"

interface ContextType {
  Name: string
}

export default function Home() {

  const { Name } = useNameContext() as ContextType;
  return (
    <div className="flex justify-center items-center h-screen">
      <p className="font-bold border-2 border-yellow-600 p-4 rounded-lg">Hello👋, I am {Name}</p>
    </div>
  )
}

Conclusion

This is how you can set up a React Context in NextJS 14. It's a bit tricky, but useful if you want to avoid the situation of prop drilling.

It could be helpful in various full-stack projects and components requiring state management systems and frequent backend calls.

This is all, Hope it adds value to your development journey.