Toni
Las 'Server Actions' son una característica recientemente introducida en la tecnología que permite la ejecución de código directamente en el servidor desde cualquier cliente, sin necesidad de crear un punto de API separado.
Simplificándolo al máximo, podemos invocar funciones definidas en el código del servidor presionando un botón en nuestro navegador, entre muchos otros casos.
Ahora os enseñaremos cómo aprovechar esta funcionalidad con casos de uso reales que hemos aplicado nosotros en este mismo sitio web.
Las 'Server Actions' son funciones que se ejecutan en el servidor y pueden ser invocadas desde el cliente. Esta funcionalidad es un avance significativo, ya que elimina la necesidad de crear puntos de API dedicados como se hacía en versiones anteriores.
Con esta herramienta, los desarrolladores tendremos una nueva experiencia de desarrollo que sin duda revolucionará y agilizará nuestros procesos de trabajo.
Para ser precisos, las 'Server Actions' no son específicas de Next.js, sino que en realidad son una funcionalidad incorporada en React, aunque aún se encuentra en fase alfa. Por lo tanto, si decidís utilizarlas, debéis saber que en cualquier momento se podría modificar su implementación y/o su funcionalidad.
Son muy versátiles y se pueden utilizar para diversos casos de uso. Os daremos algunos ejemplos:
Este nuevo concepto ofrece una gran cantidad de ventajas y seguramente descubriréis varios casos de uso donde se pueden aprovechar de manera efectiva.
Si tenéis algunos interesantes, ¡hacédnoslos llegar! :)
Vamos a entrar en materia, se pueden definir en cualquier lugar de nuestro código, con algunas excepciones.
Ten en cuenta que las 'Server Actions' solo se pueden definir en el código del servidor, ya sea en un 'Server Component' o en un archivo, pero en ningún caso se pueden definir en un 'Client Component'. Estos solo pueden importar 'Server Actions' para utilizarlas.
Antes de comenzar, debemos asegurarnos de haber habilitado las 'Server Actions' en el archivo next.config.js
, como puedes ver es una funcionalidad experimental, como te hemos mencionado anteriormente.
module.exports = {
experimental: {
serverActions: true,
}
};
Todo lo que tenemos que hacer es declarar una función asíncrona con la directiva use server
. Así lo hacemos con nuestro componente de Blogs.
async function fetchBlogs(page) {
'use server';
return await get(BLOGS, { start: page * limit, limit: limit });
}
const Blogs = async ({ start = 0, limit = 12 }) => {
const blogs = await get(BLOGS, { start: start, limit: limit });
return (
<BlogsPager
blogs={blogs}
fetchBlogs={fetchBlogs}
/>
);
}
Ten en cuenta que las 'Server Actions' deben tener argumentos y valores de retorno serializables, como se especifica en el concepto de 'Server Components' de React. Esto es necesario porque el valor de retorno de la función se serializa y se envía al cliente.
Alternativamente, podemos definir nuestras 'Server Actions' desde un archivo, como podría ser /server-actions.js
, y agregar la directiva use server
en la parte superior del archivo.
'use server'
export async function laMevaServerAction() {
// Realizar las acciones
}
export async function unaAltraServerAction() {
// Realizar las acciones
}
Tenemos varias opciones para invocarlas.
Lo lograremos utilizando la propiedad action
o onSubmit
del elemento form. Nosotros lo aplicamos en combinación con 'GraphQL' para crear los mensajes que nos envían desde el formulario de contacto del sitio web. No dudes en utilizarlo :)
async function createMessage(name, email, message) {
'use server';
return await post(
`mutation createMessage($message: MessageInput!) {
createMessage(data: $message) {
data {
id
}
}
}`,
{ message: { name: name, email: email, message: message }}
);
};
<form action={createMessage}>...</form>
Utilizaremos la propiedad onClick
del elemento button.
// Query GraphQL
const BLOGS = `
query Blogs($start: Int!, $limit: Int!) {
posts(sort: ["Rank:asc", "updatedAt:desc"], pagination: { start: $start, limit: $limit }) {
data {
attributes {
Title,
Briefing,
}
}
}
}
`
// 'Server Action'
async function fetchBlogs(page) {
'use server';
return await get(BLOGS, { start: page * limit, limit: limit });
}
// 'Server Component'
const Blogs = async ({ start = 0, limit = 12 }) => {
const blogs = await get(BLOGS, { start: start, limit: limit });
return (
<BlogsPager
blogs={blogs}
fetchBlogs={fetchBlogs}
/>
);
}
// 'Client Component'
'use client';
const BlogsPager = ({ blogs, fetchBlogs }) => {
// Nuestra lógica ...
return (
<button
onClick={ async () => {
const newBlogs = await fetchBlogs(page);
setBlogs([...blogs, [...newBlogs?.data?.posts.data]]);
}}
>...</button>
)
}
Si queremos invocar una 'Server Action' en algún otro punto de nuestro código que no sea un formulario, un botón o un input, utilizaremos el hook de React useTransition
.
'use server';
export async function afegirItem(id) {
await afegirBd(id);
revalidatePath('/item/[id]');
}
'use client';
import { useTransition } from 'react';
import { afegirItem } from '/server-actions.js'
function ClientComponent({ id }) {
const [ isPending, startTransition ] = useTransition();
return (
<button onClick={() => startTransition(() => afegirItem(id))}>...</button>
);
}
Si después de invocar una 'Server Action' queremos actualizar los datos asociados a una ruta específica de nuestro sitio web, podemos utilizar la función revalidatePath
.
Cuando utilizamos 'Server Actions' desde un formulario, estas seguirán funcionando incluso si JavaScript está deshabilitado, ya que el formulario se enviará al servidor. Por el contrario, cuando invocamos código de forma imperativa solo funcionará cuando JavaScript esté habilitado.
Siempre que sea posible, recomendamos utilizar 'Server Actions' desde formularios para garantizar que tu aplicación funcione incluso con JavaScript deshabilitado.
Next.js define las 'Server Mutations' como 'Server Actions' que mutan datos e invocan a redirect
, revalidatePath
o revalidateTag
.
Si no invocas ninguna de estas funciones, no es necesario marcar la función como 'Server Mutation'.
async function createMessage(name, email, message) {
'server mutation';
await post(
`mutation createMessage($message: MessageInput!) {
createMessage(data: $message) {
data {
id
}
}
}`,
{ message: { name: name, email: email, message: message }}
);
redirect('/gracias');
}
Las 'Server Actions' son una característica potente que nos permite ejecutar código en el servidor directamente desde el cliente sin necesidad de crear puntos de API dedicados.
Se pueden utilizar para diversas acciones, como mutar datos, realizar lógica de servidor o invocar APIs externas. Con esta nueva funcionalidad, podemos agilizar nuestros procesos de desarrollo y mejorar la experiencia del usuario.
Ten en cuenta que las 'Server Actions' se encuentran en fase alfa
y pueden cambiar en futuros lanzamientos de React.
Sin embargo, podemos aprovechar esta funcionalidad y explorar los beneficios que nos ofrece en la actualidad. Esperamos que esta explicación te sea útil para aprovechar al máximo esta nueva característica de Next.js.