Concepto clave
Las Server Actions en Next.js 15 son funciones que se ejecutan exclusivamente en el servidor, permitiendo manipular datos sin exponer APIs REST tradicionales. Piensa en ellas como "cajeros automáticos seguros": el usuario interactúa con una interfaz (el cajero), pero toda la lógica de transacciones ocurre dentro del sistema bancario protegido. Esto elimina la necesidad de crear endpoints manuales para operaciones como crear, actualizar o eliminar datos.
La seguridad es inherente porque el código nunca se envía al cliente. Sin embargo, debes protegerlas contra amenazas como CSRF (Cross-Site Request Forgery) o inyección de datos. Next.js incluye protecciones automáticas, pero como desarrollador debes validar entradas y gestionar permisos. Un error común es asumir que "porque es del servidor, ya es seguro", ignorando validaciones básicas.
Cómo funciona en la práctica
Para usar una Server Action, la defines en un archivo del servidor (ej: actions.ts) con 'use server' y la importas en un componente. Aquí un ejemplo paso a paso para un formulario de contacto:
- Crea
app/actions/contact.ts:'use server' import { revalidatePath } from 'next/cache' export async function sendContact(formData: FormData) { const name = formData.get('name')?.toString() const email = formData.get('email')?.toString() // Validación: verifica que los campos no estén vacíos if (!name || !email) { return { error: 'Faltan campos requeridos' } } // Lógica de negocio: guardar en base de datos await db.contacts.create({ data: { name, email } }) revalidatePath('/contacts') return { success: true } } - Úsala en un componente React:
'use client' import { sendContact } from '@/app/actions/contact' export default function ContactForm() { async function handleSubmit(formData: FormData) { const result = await sendContact(formData) if (result.error) alert(result.error) } return ( <form action={handleSubmit}> <input name="name" /> <input name="email" type="email" /> <button type="submit">Enviar</button> </form> ) }
Observa que sendContact solo se ejecuta en el servidor, protegiendo la lógica de base de datos.
Caso de estudio
Imagina una app de tareas (todo-list) donde los usuarios pueden agregar y completar tareas. Usando Server Actions, implementamos:
- Acción:
addTask(title: string)– valida el título, lo guarda en DB, y revalida la lista. - Seguridad: Verificamos que el usuario esté autenticado (usando cookies seguras) y que el título no exceda 100 caracteres para evitar ataques de desbordamiento.
- Flujo: El cliente llama a
addTaskdesde un formulario; el servidor procesa y devuelve el estado actualizado sin exponer la consulta SQL.
Dato importante: En producción, siempre combina Server Actions con middleware de autenticación y límites de tasa (rate limiting) para prevenir abusos.
Errores comunes
- No validar entradas: Asumir que los datos del formulario son seguros. Siempre valida tipos, longitudes y formatos en el servidor.
- Exponer errores detallados: Enviar mensajes de error del servidor al cliente puede filtrar información sensible. Usa respuestas genéricas como "Algo salió mal".
- Olvidar revalidación: No usar
revalidatePathorevalidateTagdespués de mutar datos, dejando la caché desactualizada. - Ignorar CSRF: Aunque Next.js lo maneja, deshabilitarlo sin razón compromete la seguridad. Verifica que las cookies estén configuradas correctamente.
- Manejo inadecuado de archivos: Si subes archivos, valida tipos y tamaños en el servidor para evitar ataques de inyección.
Checklist de dominio
- Puedo crear una Server Action que valide datos de formulario y los guarde en una base de datos.
- Sé cómo proteger acciones con autenticación (ej: usando cookies o tokens en middleware).
- Entiendo cuándo usar
revalidatePathpara actualizar cachés después de mutaciones. - Reconozco y evito errores comunes como no validar entradas o exponer detalles de error.
- Puedo integrar Server Actions en componentes cliente manteniendo la interactividad.
- Sé cómo probar Server Actions en desarrollo usando herramientas como console.log en el servidor.
- Comprendo la diferencia entre Server Actions y APIs tradicionales en términos de seguridad y flujo de datos.
Implementa una Server Action segura para actualizar perfil de usuario
En este ejercicio, crearás una Server Action que permita a usuarios actualizar su nombre en un perfil, con validaciones de seguridad. Sigue estos pasos:
- Crea un archivo
app/actions/profile.tsy define una acciónupdateProfilecon'use server'. - La acción debe aceptar un objeto con
userId(string) ynewName(string). - Implementa validaciones: verifica que
userIdcorresponda al usuario autenticado (simula con una constante por ahora) y quenewNametenga entre 2 y 50 caracteres. - Si las validaciones pasan, simula guardar en una base de datos (usa
console.log) y devuelve un objeto con{ success: true, message: 'Perfil actualizado' }. - En caso de error, devuelve
{ success: false, error: 'Mensaje descriptivo' }sin detalles internos. - Crea un componente cliente en
app/profile/page.tsxque use un formulario para llamar a esta acción y muestre el resultado.
- Usa
typeofy.lengthpara validar el nombre en la Server Action. - Recuerda que las Server Actions deben manejar errores con try-catch para no crashear el servidor.
- En el componente cliente, usa
useStatepara manejar el estado de envío y respuesta.
Evalua tu comprension
Completa el quiz interactivo de arriba para ganar XP.