This error occurs when attempting to use React Context API (createContext) directly in a Next.js Server Component. Context relies on client-side runtime and cannot be used in components that render on the server.
This error appears when you try to use React's Context API within a Server Component in Next.js 13+ App Router. Server Components are rendered on the server and streamed to the client, but React Context requires a stable component identity between renders and client-side state management, which are not available in the server environment. The error typically manifests when you call `createContext()` in a file that doesn't have the `"use client"` directive, or when you try to use a Context Provider or Consumer in a Server Component. Since Server Components don't have a persistent identity across requests and cannot maintain client-side state, the Context API is fundamentally incompatible with them. This is a deliberate architectural constraint in React Server Components, designed to ensure that server-rendered components remain stateless and cacheable. To use Context in the App Router, you must explicitly mark components as Client Components.
Extract your context creation and provider into a dedicated file with the "use client" directive:
// contexts/theme-provider.tsx
"use client";
import { createContext, useContext, useState } from 'react';
type Theme = 'light' | 'dark';
const ThemeContext = createContext<{
theme: Theme;
setTheme: (theme: Theme) => void;
} | undefined>(undefined);
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme must be used within ThemeProvider');
}
return context;
}This isolates all client-side Context logic into a Client Component.
Now you can import the Client Component provider into your Server Component layout:
// app/layout.tsx (Server Component - no "use client")
import { ThemeProvider } from '@/contexts/theme-provider';
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<ThemeProvider>
{children}
</ThemeProvider>
</body>
</html>
);
}The layout remains a Server Component, but it can render the Client Component provider. All children (both Server and Client Components) can then access the context.
Use the context in any Client Component by marking it with "use client":
// components/theme-toggle.tsx
"use client";
import { useTheme } from '@/contexts/theme-provider';
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Current theme: {theme}
</button>
);
}Never attempt to call useContext() or consume context in a Server Component.
Instead of wrapping your entire app, render providers only where needed:
// app/dashboard/layout.tsx
import { DashboardProvider } from '@/contexts/dashboard-provider';
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<DashboardProvider>
{children}
</DashboardProvider>
);
}This helps Next.js optimize the static parts of your Server Components and reduces the client-side JavaScript bundle.
Server Component Composition Pattern: You can pass Server Components as children or props to Client Components. This allows you to place a Client Component provider high in the tree while still nesting Server Components inside it. The Server Components are rendered on the server first, then the result is passed to the Client Component.
Alternative State Management: For truly global state that doesn't need reactivity in Server Components, consider:
- Server-side solutions: cookies, headers, searchParams
- Database queries with React Server Components (no context needed)
- URL state for navigation-related state
- Client-side libraries like Zustand or Jotai for complex client state
Multiple Providers: When composing multiple context providers, create a single Providers client component that wraps all providers:
"use client";
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider>
<AuthProvider>
<AnalyticsProvider>
{children}
</AnalyticsProvider>
</AuthProvider>
</ThemeProvider>
);
}Then import this single Providers component in your root layout.
Performance Considerations: Remember that any component marked with "use client" (and its imports) will be included in the client-side JavaScript bundle. Keep client components small and focused to minimize bundle size.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite