Componentes de Servidor
React Server Components, Servidor vs Cliente, y patrones de obtención de datos
¿Qué son los Server Components?
Los React Server Components (RSC) son un cambio fundamental en cómo funcionan las aplicaciones React. En lugar de enviar todo el código de componentes al navegador, los Server Components se ejecutan solo en el servidor. Pueden acceder directamente a bases de datos, sistemas de archivos y APIs sin enviar ese código al cliente.
El resultado: bundles de JavaScript más pequeños, cargas de página más rápidas y obtención de datos más simple. Los Server Components están completamente integrados en frameworks como Next.js 13+ (App Router).
Servidor vs Cliente
🖥️ Server Components
- • Se ejecutan solo en el servidor
- • Pueden acceder a bases de datos
- • Sin impacto en el tamaño del bundle
- • Pueden usar async/await
- • No pueden usar estado ni efectos
🌐 Client Components
- • Se ejecutan en el navegador
- • Pueden usar useState, useEffect
- • Manejan interacciones del usuario
- • Acceden a APIs del navegador
- • Necesitan directiva "use client"
Componentes de Servidor Básicos
// app/users/page.jsx — Server Component (por defecto)
async function UsersPage() {
const users = await fetch('https://api.example.com/users').then(r => r.json());
return (
<div>
<h1>Usuarios</h1>
<ul>
{users.map(user => (
<li key={user.id}>{user.name} — {user.email}</li>
))}
</ul>
</div>
);
}
Componentes Cliente con "use client"
// components/LikeButton.jsx — Client Component
'use client';
import { useState } from 'react';
export function LikeButton({ postId, initialLikes }) {
const [likes, setLikes] = useState(initialLikes);
const [isLiked, setIsLiked] = useState(false);
async function handleLike() {
setIsLiked(!isLiked);
setLikes(prev => isLiked ? prev - 1 : prev + 1);
await fetch(`/api/posts/${postId}/like`, { method: 'POST' });
}
return (
<button onClick={handleLike}>
{isLiked ? '❤️' : '🤍'} {likes}
</button>
);
}
Componiendo Server y Client Components
// app/posts/[id]/page.jsx — Server Component
import { db } from '@/lib/database';
import { LikeButton } from '@/components/LikeButton';
async function PostPage({ params }) {
const post = await db.post.findUnique({
where: { id: params.id },
include: { author: true },
});
return (
<article>
{/* Contenido estático renderizado en servidor — cero JS */}
<h1>{post.title}</h1>
<p>Por {post.author.name}</p>
{/* Partes interactivas son Client Components */}
<LikeButton postId={post.id} initialLikes={post.likes} />
</article>
);
}
✅ Mejores Practicas
- • Mantén los componentes como Server Components por defecto
- • Solo agrega "use client" cuando sea necesario
- • Empuja los límites de Client Components lo más abajo posible en el árbol
- • Pasa datos obtenidos del servidor a Client Components via props
- • Nunca importes código solo del servidor en Client Components
- • Usa el paquete npm
server-onlypara prevenir importaciones accidentales