context api in next js
user profile avatar
Tech Wizard

Published on • 🕑3 min read

Authentication in NextJS Part 2: UseContext

1likes2

Blog views760

Listen to this blog

This blog is a continuation of the previous blog on handling auth in next js where we discussed the use of JWT tokens in server actions to fetch user data. In the blog, we talked about creating an api roiute (/api/me) where we can use context to fetch user data. This blog discusses how to do that.

What is Context-API?

Context-API is a way to make a global store in an application where we can store data and variables. The variables and data which are in the context can be accessed from any page or component without manually passing the props from the parent component to the child component.

Why use Context-API?

Although there are many ways to achieve this functionality in our application, context API has its own place and advantages. These are some of the benefits of using it over others.

  • If we do not use context API or any other library and simply pass props from parents to the child and then from this child to another child, it will become a very hectic and bad way to write code as the number of children and props increases.
  • Context API is very light and fast in comparison to other state management libraries like redux and recoil as it is inbuilt in Next.js.

Using the Context-API effectively

As you know by now, NextJS leverages the power of server side rendering to make the page faster. Since every page is a server code by default, useContext is not supported in pages that have not specifically declared "use client" at the top. 

There are three main steps in creating the global store using context API and making the user information available globally.

Step 1: Creating the context

Create a folder in the outmost directory of your app and name it providers. In this folder, add an index.js file, where we will create a user context that will be exported to pages that need to check whether the user exists.

//index.js
"use client";
import { createContext, useContext, useEffect, useState } from "react";
const UserContext = createContext({});
export function UserContextProvider({ children }) {
  const [user, setUser] = useState(null);
  useEffect(() => {
    const fetchUser = async () => {
      try {
        const response = await fetch(`${baseUrl}/me`);
        const data = await response.json();
        setUser(data);
      } catch (error) {
        console.error("Failed to fetch user", error);
      }
    };
      fetchUser();
  }, []);
  return <UserContext.Provider value={user}>{children}</UserContext.Provider>;
}
// Make useUserContext Hook to easily use our context throughout the application
export function useUserContext() {
  return useContext(UserContext);
}

Step 2: Wrapping our app in Context

To ensure that each component can have access to the user object, we need to wrap our layout.ts file with the context provider. In the layout.js file, add the following code:

import "../globals.css";
import { UserContextProvider } from "@/providers";
export const metadata = {
  title: "",
  description:  "",
};
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <UserContextProvider>
            <main>
              {children}
            </main>
        </UserContextProvider>
      </body>
    </html>
  );
}


Step 3: Using the Context

The last step is ensuring that components that need access to context can have such access. Ensure that any component using context is a client component. For example, let add context to the navbar:

// components/NavBar.js
"use client";
Import dynamic from 'next/dyanmic';
import { useUserContext } from '../context/user';
export const dynamic = "force-dynamic";
export default function NavBar() {
 // Getting user object using useUserContext Hook
  const user  = useUserContext();
  return (
    <div className="container">
        <h1>NavBar</h1>
        <p>Logged in User: <strong>{user?.name}</strong></p>
        <p>User token: <strong>{user?.token}</strong></p>  
    </div>
  )
}

Conclusion:

If we want an easy, fast, and lightweight store for our project, then context-API is the best choice. Remember to add additional checks on whether the user is present to prevent errors. For example, in my code i check if the user token exists but has expired so I can tell users their session has expired.

Like what you see? Share with a Friend

1 Comments

2 Likes

Comments (1)

sort comments

Before you comment please read our community guidelines


Please Login or Register to comment

user profile avatar

the don

online

Published on

Context API is way simpler than using redux