stackademic

The leading education platform for anyone with an interest in software development.

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