This error occurs when trying to use React client hooks like useState, useEffect, or useRef in a Server Component. In Next.js 13+, all components are Server Components by default and must be explicitly marked as Client Components to use client-side hooks.
This error appears when you attempt to use React client hooks (useState, useEffect, useRef, useContext, etc.) in a component that Next.js treats as a Server Component. In Next.js 13 and later with the App Router, all components in the app directory are Server Components by default unless explicitly marked otherwise. Server Components run only on the server during build time or on each request, allowing for better performance through reduced JavaScript bundle sizes and direct database access. However, they cannot use browser-specific APIs or React hooks that depend on client-side interactivity and state management. The error message specifically mentions "use" because React hooks follow the naming convention of starting with "use" (useState, useEffect, etc.). When Next.js detects a hook being called in a Server Component, it throws this error to prevent runtime failures, as these hooks require a browser runtime to function properly.
The most straightforward fix is to mark the component as a Client Component by adding the "use client" directive at the very top of the file, before any imports.
'use client';
import { useState } from 'react';
export default function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}The directive must be at the very top of the file and is case-sensitive. It tells Next.js that this component and all its imports should be bundled for the client.
Not all components need to be Client Components. Review your component tree to determine which components truly need client-side features:
Need "use client":
- Components using useState, useEffect, useRef, useReducer
- Event handlers (onClick, onChange, onSubmit)
- Browser APIs (window, document, localStorage)
- Custom hooks that use any of the above
Don't need "use client":
- Static content display components
- Components only using props and rendering JSX
- Data fetching using async/await (Server Components support this natively)
- Components accessing databases or APIs directly on the server
Keep as many components as Server Components as possible for better performance.
Instead of marking entire page components as Client Components, extract interactive portions into smaller Client Components:
// app/dashboard/page.tsx (Server Component)
import ClientCounter from './ClientCounter';
export default async function DashboardPage() {
const data = await fetchDataFromDatabase(); // Server-side data fetching
return (
<div>
<h1>Dashboard</h1>
<p>Static server content: {data.summary}</p>
<ClientCounter /> {/* Only this is a Client Component */}
</div>
);
}// app/dashboard/ClientCounter.tsx (Client Component)
'use client';
import { useState } from 'react';
export default function ClientCounter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}This pattern keeps most of your page as a Server Component while isolating client interactivity.
If you have custom hooks that use React client hooks internally, add "use client" to the hooks file:
// hooks/useLocalStorage.ts
'use client';
import { useState, useEffect } from 'react';
export function useLocalStorage(key: string, initialValue: string) {
const [value, setValue] = useState(initialValue);
useEffect(() => {
const stored = localStorage.getItem(key);
if (stored) setValue(stored);
}, [key]);
return [value, setValue] as const;
}Any component importing this hook will automatically become a Client Component.
Many UI libraries and third-party components use client hooks internally. Wrap them in your own Client Component:
// components/ThirdPartyWrapper.tsx
'use client';
import SomeLibraryComponent from 'some-library';
export default function ThirdPartyWrapper({ children }: { children: React.ReactNode }) {
return <SomeLibraryComponent>{children}</SomeLibraryComponent>;
}Then import ThirdPartyWrapper in your Server Components instead of the library component directly.
Common mistakes with "use client" directive:
Incorrect:
import { useState } from 'react';
'use client'; // ❌ Must be first
export default function MyComponent() { ... }"use client"; // ❌ Must use single quotes
import { useState } from 'react';Correct:
'use client'; // ✅ First line, single quotes
import { useState } from 'react';
export default function MyComponent() { ... }The directive is case-sensitive and must use single quotes, not double quotes.
If a file re-exports components from other files, the "use client" directive may not propagate correctly:
Problem:
// components/index.ts
export { Counter } from './Counter'; // Counter has "use client"
export { Display } from './Display'; // Display is Server Component// app/page.tsx (Server Component)
import { Counter, Display } from '@/components'; // May cause issuesSolution:
Import directly from the component files:
// app/page.tsx
import Counter from '@/components/Counter'; // Direct import preserves "use client"
import Display from '@/components/Display';Or ensure the barrel export file includes "use client" if all exports are Client Components.
Composition Patterns: The recommended pattern is to keep Server Components as the default and compose Client Components into them. This allows you to fetch data on the server (which is faster and more secure) while maintaining interactivity where needed. You can even pass Server Components as children to Client Components using the composition pattern.
Performance Considerations: Every "use client" directive creates a new client boundary, which means everything imported in that file gets bundled for the client. Be strategic about where you place these directives - use them as deep in your component tree as possible to minimize client-side JavaScript.
Context Providers: Context providers that use React Context API require "use client" because useContext is a client hook. If you need to wrap your entire app in a provider, create a separate client component for the provider wrapper and import it into your root layout.
Migration from Pages Router: When migrating from Next.js 12 or earlier (Pages Router), remember that all components were client components by default. In App Router (Next.js 13+), the default is reversed - everything is a Server Component unless marked otherwise. Audit your components during migration and add "use client" only where necessary.
Environment Variables: Be cautious with "use client" and environment variables. Only environment variables prefixed with NEXT_PUBLIC_ are available in Client Components. Server-only secrets should remain in Server Components.
TypeScript Considerations: The directive is a string literal at the file level and doesn't require TypeScript types. However, ensure your tsconfig.json includes "moduleResolution": "bundler" or "node16" for proper module resolution in Next.js 13+.
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