How to Use the Context API in Next.js (App Router, React 19)

Abhilash SahooFounder & CEO, Infyways
Published
Updated
Reading time
5 min read
Use Context API in Next.js
On this page 11 sections

Updated 12 October 2026 · By Abhilash Sahoo, Infyways

To use the Context API in Next.js (App Router), create the context and its provider in a Client Component marked 'use client', wrap your app (or part of it) with the provider in layout.tsx, and read it with useContext (or React 19's use) in Client Components. Server Components cannot read React context; pass server data to the provider as props instead.

How do I set up Context in the Next.js App Router?

// app/providers/theme-provider.tsx
'use client';
import { createContext, useContext, useState } from 'react';

type Theme = 'light' | 'dark';
const ThemeContext = createContext<{ theme: Theme; toggle: () => void } | null>(null);

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState<Theme>('light');
  return (
    <ThemeContext value={{ theme, toggle: () => setTheme(t => (t === 'light' ? 'dark' : 'light')) }}>
      {children}
    </ThemeContext>
  );
}

export function useTheme() {
  const ctx = useContext(ThemeContext);
  if (!ctx) throw new Error('useTheme must be used inside ThemeProvider');
  return ctx;
}
// app/layout.tsx (Server Component)
import { ThemeProvider } from './providers/theme-provider';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body><ThemeProvider>{children}</ThemeProvider></body>
    </html>
  );
}

React 19 (used by current Next.js) lets you render <ThemeContext> directly as the provider; <ThemeContext.Provider> still works. Server Components can be passed as children through a Client provider without becoming client code.

Context vs other state options in Next.js

NeedUse
Theme, locale, auth user, UI state shared by many componentsReact Context
Frequently changing global state with many subscribersZustand, Jotai or Redux Toolkit (avoid re-rendering every consumer)
Server data (fetching, caching, revalidation)Fetch in Server Components, or TanStack Query / SWR on the client
State that should be in the URL (filters, tabs)Search params

Full guide

Simplifying State Management in Next.js Applications

Highlights:

  • Learn how to use Context API in Next.js
  • Simplify state management with useContext and createContext
  • Explore practical examples using server and client components

State management is crucial when developing scalable applications. In Next.js, using the Context API for managing state simplifies data sharing across components. This guide explains how to set up and use the Context API in your Next.js application effectively.

Why Use the Context API in Next.js?

Context api nextjs

Next.js offers powerful tools for both server and client-side development. However, managing state across deeply nested components can be challenging. With Next.js Context, you can:

  • Avoid "prop drilling" by passing data directly to components.
  • Share global state using createContext and useContext hooks.
  • Simplify state management in both server components and client components.

For example, instead of passing a user object down multiple layers of components, you can use a Next.js Provider to make it accessible across the entire app.

Setting Up Context API in Next.js

Step 1: Create a Context

Start by creating a context using React’s createContext function. In your Next.js application, define it as a separate module:

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

export const UserContext = createContext(null);  

export function UserProvider({ children }) {  
  const [user, setUser] = useState(null);  

  return (  
    <UserContext.Provider value={{ user, setUser }}>  
      {children}  
    </UserContext.Provider>  
  );  
}  

In this code:

  • createContext: Creates a context object.
  • UserProvider: Wraps components and provides access to the user state.

Step 2: Use Context in Components

To access context values, use the useContext hook. Here’s an example of consuming the UserContext:

import { useContext } from 'react';  
import { UserContext } from '../context/UserContext';  

export default function UserProfile() {  
  const { user, setUser } = useContext(UserContext);  

  if (!user) {  
    throw new Error("No user data available");  
  }  

  return (  
    <div>  
      <h1>Welcome, {user.name}!</h1>  
      <button onClick={() => setUser(null)}>Logout</button>  
    </div>  
  );  
}  

Step 3: Wrap Your Application

Wrap your app with the UserProvider in pages/_app.js:

import { UserProvider } from '../context/UserContext';

export default function App({ Component, pageProps }) {
return (

);
}

his makes the user state available throughout the app.

Using Context API with Server Components

Server Components cannot use useContext, and React context is not available on the server. Fetch the data in a Server Component (such as layout.tsx) and pass it to the Client provider as a prop:

// app/layout.tsx
const user = await getUser();
return <UserProvider initialUser={user}>{children}</UserProvider>;

Advanced Tips and Best Practices

Error Handling in Context

When consuming context values, always handle cases where the context might not be available:

const context = useContext(UserContext);
if (!context) {
throw new Error("UserContext must be used within a UserProvider");
}

Using Context with useState

Leverage useState from React to manage local state within your context:

export const ThemeContext = createContext();  

export function ThemeProvider({ children }) {  
  const [theme, setTheme] = useState('light');  

  return (  
    <ThemeContext.Provider value={{ theme, setTheme }}>  
      {children}  
    </ThemeContext.Provider>  
  );  
}  

Combining Context with Other Hooks

Combine useContext with useEffect to fetch and update data dynamically:

import { useEffect, useContext } from 'react';  
import { UserContext } from '../context/UserContext';  

export default function FetchUser() {  
  const { setUser } = useContext(UserContext);  

  useEffect(() => {  
    async function fetchData() {  
      const data = await fetch('/api/user').then((res) => res.json());  
      setUser(data);  
    }  

    fetchData();  
  }, [setUser]);  

  return <div>Loading user data...</div>;  
}  

Key Benefits of Context API in Next.js

  • Effortless State Sharing: No need for complex state management libraries.
  • Server and Client Compatibility: Works seamlessly with server-side rendering (SSR) and client components.
  • Improved Code Readability: Cleaner structure without excessive props.

Conclusion

Using the Context API in Next.js is a powerful way to manage global state. By combining createContext, useContext, and Next.js Provider, you can streamline state management for server and client components alike.

Whether you're building SEO-friendly applications with server-side rendering or dynamic client-side apps, the Context API offers a lightweight yet robust solution.

Explore more on Next.js state management in the official Next.js documentation and start simplifying your development workflow today!

Looking for a Next.js Developer? Hire now!

Frequently asked questions

No. Context only works in Client Components; fetch data on the server and pass it to a Client provider as props.

In a Client Component marked use client, rendered from app/layout.tsx or a nested layout.

No. Server Components passed as children keep rendering on the server.

Context for rarely changing shared values; Zustand or similar for frequently updated global state.

Share this article

Filed under Web Development

Need help with this?

Talk to the Infyways team.

From audits and upgrades to performance and long-term care, we build and maintain the platforms our clients ship on.