Next.js Client Components

Add interactivity with use client, hooks, and browser APIs

Overview

Client Components run in the browser. Add the 'use client' directive at the top of a file to use React state, effects, event handlers, and browser-only APIs. Keep them as small as possible at the leaves of your component tree.

Syntax / Usage

'use client'

import { useState } from 'react'

export function Counter() {
  const [count, setCount] = useState(0)
  return (
    <button onClick={() => setCount((c) => c + 1)}>
      Count: {count}
    </button>
  )
}

Import a Client Component into a Server Component:

// app/page.tsx — Server Component
import { Counter } from '@/components/Counter'

export default function Page() {
  return (
    <main>
      <h1>Dashboard</h1>
      <Counter />
    </main>
  )
}

Examples

Form with client-side validation:

'use client'

export function ContactForm() {
  const [error, setError] = useState<string | null>(null)

  async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault()
    const form = new FormData(e.currentTarget)
    const email = String(form.get('email'))
    if (!email.includes('@')) {
      setError('Invalid email')
      return
    }
    await fetch('/api/contact', { method: 'POST', body: form })
  }

  return (
    <form onSubmit={onSubmit}>
      <input name="email" />
      {error && <p>{error}</p>}
      <button type="submit">Send</button>
    </form>
  )
}

Common Mistakes

  • Adding 'use client' to files that only render static markup
  • Importing server-only modules (fs, DB clients) into Client Components
  • Bundling large libraries in client components without dynamic import
  • Prop drilling server secrets through client props

See Also

server-components app-router use-state use-effect