Publicado por Diana Huaripayta G. el Aug 15, 2025
"use client" en Next.js: Guía clara para entenderlo y usarlo bien
En Next.js, desde la llegada del App Router (v13+), todo cambió en la forma en que pensamos sobre dónde se ejecuta nuestro código.
Antes, todo React se ejecutaba en el cliente (navegador) por defecto.
Ahora, en el mundo moderno de Next.js, los componentes se ejecutan en el servidor por defecto y el cliente es la excepción.
Next.js 12 y anteriores - TODO en cliente por defecto
function MyComponent() { const [count, setCount] = useState(0) // ✅ Funcionaba sin problemas return <div>Count: {count}</div> }
Next.js 13+ App Router - Server Component por defecto
function MyComponent() { const [count, setCount] = useState(0) // ❌ Error! useState no existe en servidor return <div>Count: {count}</div> }
Next.js 13+ - Declarando explícitamente como Client Component
"use client" function MyComponent() { const [count, setCount] = useState(0) // ✅ Ahora sí funciona return <div>Count: {count}</div> }
1. ¿Qué es "use client"?
"use client" es una directiva especial que le dice a Next.js:
“Este componente debe ejecutarse en el lado del cliente (navegador) y no en el servidor”.
Esto es necesario cuando tu componente necesita:
- Interactividad (botones, formularios, sliders, etc.).
- Hooks de React que dependen del navegador (useState, useEffect, useRef…).
- APIs del navegador (localStorage, window, document…).
- Librerías que solo funcionan en el cliente (por ejemplo, Framer Motion para animaciones).
Ejemplo:
"use client"; import { useState } from "react"; export default function Contador() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(count + 1)}> Contador: {count} </button> ); }
La documentación de Next.js recomienda. 👀
You do not need to add the
'use client'
directive to every file that contains Client Components. You only need to add it to the files whose components you want to render directly within Server Components. The'use client'
directive defines the client-server boundary, and the components exported from such a file serve as entry points to the client.
El Concepto de "Frontera" (Boundary) Aquí viene la parte crucial que muchos developers no entienden: Es decir , "use client" NO es heredable hacia arriba, solo hacia abajo Ejemplo:
// app/page.jsx - Server Component 📌 export default function HomePage() { return ( <div> <h1>Bienvenid@ (renderizado en servidor)</h1> {/* ⬇️ AQUÍ SE CRUZA LA FRONTERA ⬇️ */} <InteractiveSection /> <footer>Footer (renderizado en servidor)</footer> </div> ) }
👇
// components/InteractiveSection.jsx - PUNTO DE ENTRADA AL CLIENTE 📌 "use client" import Button from './Button' import Modal from './Modal' import Counter from './Counter' export default function InteractiveSection() { return ( <div> <h2>Sección interactiva</h2> {/* ✅ Todos estos se ejecutan en cliente automáticamente */} <Button /> <Modal /> <Counter /> </div> ) }
👇
// components/Button.jsx - SIN "use client" (hereda del padre) 📌 import { useState } from 'react' export default function Button() { const [clicked, setClicked] = useState(false) // ✅ Funciona sin "use client" return ( <button onClick={() => setClicked(!clicked)}> {clicked ? '¡Clickeado!' : 'Click me'} </button> ) }
❌ Error Común: Poner "use client" en cada archivo
// ❌ MALO - Redundante e innecesario "use client" // No necesario function Button() { return <button>Click</button> } "use client" // No necesario function Modal() { return <div>Modal</div> } "use client" // Solo este es necesario function InteractiveSection() { return ( <div> <Button /> {/* Ya es cliente por herencia */} <Modal /> {/* Ya es cliente por herencia */} </div> ) }
¿Cuándo Usar "use client"?
✅ Cuándo SÍ usarlo:
1. Estados y Hooks de React
"use client" import { useState, useEffect } from 'react' function UserProfile() { const [user, setUser] = useState(null) useEffect(() => { // Lógica que requiere el navegador fetchUserProfile() }, []) return <div>Perfil: {user?.name}</div> }
2. Event Handlers
"use client" function ContactForm() { const handleSubmit = (e) => { e.preventDefault() // ❌ Sin "use client" esto falla console.log('Formulario enviado') } return ( <form onSubmit={handleSubmit}> <button type="submit">Enviar</button> </form> ) }
3. APIs del Navegador
"use client" function ThemeToggle() { const toggleTheme = () => { // ❌ `localStorage` no existe en el servidor const currentTheme = localStorage.getItem('theme') const newTheme = currentTheme === 'dark' ? 'light' : 'dark' localStorage.setItem('theme', newTheme) } return <button onClick={toggleTheme}>Cambiar Tema</button> }
4. Librerías que Dependen del DOM
"use client" import { useEffect } from 'react' import { gsap } from 'gsap' // Librería de animación function AnimatedComponent() { useEffect(() => { // ❌ GSAP necesita acceso al DOM gsap.from('.box', { duration: 2, x: -100 }) }, []) return <div className="box">Animación</div> }
✅ Cuándo NO usarlo:
1. Contenido Estático
// ✅ Perfecto como Server Component function AboutPage() { return ( <div> <h1>Acerca de Nosotros</h1> <p>Somos una empresa...</p> </div> ) }
2. Fetch de Datos
// ✅ Mejor en el servidor async function BlogPosts() { const posts = await fetch('https://api.blog.com/posts') return ( <div> {posts.map(post => ( <article key={post.id}> <h2>{post.title}</h2> <p>{post.excerpt}</p> </article> ))} </div> ) }
Consejo estos 3 Pasos 👇
Paso 1: Identifica la Necesidad
¿Tu componente necesita alguno de estos?
useState
,useEffect
, hooks de React- Event handlers (
onClick
,onSubmit
, etc.) - APIs del navegador (
localStorage
,window
,document
) - Librerías que solo funcionan en el cliente
Paso 2: Encuentra el Punto de Entrada
Busca el componente padre más alto que necesite ser cliente.
Paso 3: Declara la Frontera
Pon "use client"
solo en ese componente padre.
Beneficios de Esta Estrategia
🚀 Mejor Rendimiento
- Máximo contenido renderizado en servidor
- JavaScript mínimo enviado al cliente
- Tiempo de carga más rápido
🧹 Código Más Limpio
- No repites
"use client"
innecesariamente - Estructura más clara y mantenible
- Separación clara entre servidor y cliente
💡 SEO Mejorado
- Contenido estático indexable inmediatamente
- No depende de JavaScript para mostrar contenido
Conclusión
La directiva "use client"
en Next.js 13+ representa un cambio fundamental en cómo pensamos sobre las aplicaciones React. La clave está en:
- Entender que Server Components son el nuevo predeterminado
- Usar "use client" solo cuando realmente necesites interactividad
- Declarar la frontera una sola vez en el punto de entrada más alto
- Dejar que los componentes hijos hereden automáticamente
Recuerda 🤓: menos "use client"
significa mejor rendimiento y experiencia de usuario. Úsalo estratégicamente, no por defecto.