Inicio / Artículos / Envío de datos con consulta RTK: Una guía práctica sobre mutaciones

Envío de datos con consulta RTK: Una guía práctica sobre mutaciones

Aprenda cómo utilizar builder.mutation() en RTK Query para enviar solicitudes POST, gestionar los estados de carga y error, y crear un componente de formulario funcional.

1875 palabras

Introducción

Anteriormente explicamos cómo configurar Redux Toolkit Query (RTK Query) y ejecutar operaciones de lectura con builder.query(). Esto nos permitió obtener datos de una API y mostrarlos dentro de una aplicación React sin tener que implementar manualmente useEffect(), useState() o lógica de solicitud personalizada.

No obstante, leer datos es solo la mitad de la historia al trabajar con APIs. La mayoría de las aplicaciones también necesitan formas de agregar, modificar o eliminar registros en el servidor.

Considere algunos escenarios comunes:

  • Un formulario de registro envía los detalles de una nueva cuenta.
  • Una pantalla de inicio de sesión envía las credenciales para su verificación.
  • Una plataforma de blogs publica nuevos artículos.
  • Una tienda en línea realiza nuevos pedidos.
  • Una aplicación de tareas guarda las tareas recién añadidas.

Cada una de estas acciones envía información desde el cliente hacia el servidor, y eso se hace normalmente a través de una solicitud HTTP POST.

RTK Query no trata las llamadas POST como consultas; las considera mutaciones.

Este artículo explica cómo enviar datos con builder.mutation(). Desglosaremos cada parte del código y cada configuración para que entienda no solo qué escribir, sino también por qué es importante cada elemento.

Comprensión de los métodos HTTP

Antes de adentrarnos en el código, es útil revisar los diferentes verbos HTTP y su propósito.

Una API REST típica expone varias operaciones:

Método Propósito Ejemplo
GET Leer datos Obtener a todos los usuarios
POST Añadir nuevos datos
Crear un usuario PUT Sobrescribir un recurso existente Sustituir un registro de usuario PATCH Modificar parte de un recurso Cambiar el nombre de un usuario DELETE Eliminar datos Borrar un usuario

Esta guía se centra en POST, el método utilizado para crear nuevos recursos en un servidor.

¿Por qué POST no utiliza builder.query()?

Este es un punto de confusión común entre los principiantes.

Si builder.query() puede recuperar datos, ¿por qué la misma función no puede enviar datos al servidor?

La razón se debe a para qué fue diseñado cada herramienta.

Consultas

Las consultas existen para obtener información.

Ejemplos típicos:

  • Obtener usuarios
  • Obtener productos
  • Obtener pedidos
  • Obtener publicaciones

Dado que los mismos datos pueden solicitarse repetidamente, las consultas almacenan automáticamente sus resultados en caché.

Mutaciones

Las mutaciones existen para modificar datos.

Ejemplos típicos:

  • Crear usuario
  • Actualizar usuario
  • Borrar usuario
  • Iniciar sesión
  • Registrarse

Una mutación indica al servidor que algo necesita cambiar.

Esa distinción es la razón por la cual RTK Query maneja las mutaciones de forma separada de las consultas.

Qué vamos a construir

Vamos a crear un formulario básico que envíe un nuevo usuario al servidor.

El endpoint de destino es:

https://jsonplaceholder.typicode.com/users

Y la carga útil enviada en el cuerpo de la solicitud tendrá este aspecto:

{
  "name": "John Doe",
  "email": "john@example.com"
}

Estructura del proyecto

src
│
├── app
│   └── store.js
│
├── services
│   └── api.js
│
├── components
│   └── AddUser.jsx
│
├── App.jsx
│
└── main.jsx

La configuración del almacén Redux permanece igual que antes. Lo único que necesitamos agregar es un punto de extremo para mutaciones y un componente que maneje el envío del formulario.

Paso 1: Crear un punto de extremo para mutaciones

Abra el archivo del servicio API:

src/services/api.js

Luego agregue la nueva definición de punto de extremo dentro del objeto endpoints.

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
export const api = createApi({
  reducerPath: "api",  baseQuery: fetchBaseQuery({
    baseUrl: "https://jsonplaceholder.typicode.com/",
  }),  endpoints: (builder) => ({    addUser: builder.mutation({      query: (newUser) => ({
        url: "users",
        method: "POST",
        body: newUser,
      }),    }),  }),});export const {
  useAddUserMutation,
} = api;

Analicemos esta línea por línea.

Comprensión de builder.mutation()

addUser: builder.mutation({

Mientras que builder.query() está diseñado para obtener datos, builder.mutation() es el que se utiliza cuando se necesita modificar algo en el servidor.

Ejemplos comunes de su uso:

  • Crear usuarios
  • Registrar cuentas
  • Conectarse
  • Actualizar productos
  • Borrar publicaciones

Cada vez que tu aplicación escribe o modifica datos en el backend, una mutación es la herramienta adecuada.

Comprensión de query()

query: (newUser) => ({

Esta función recibe los datos que le pasas desde tu código de React.

Por ejemplo, si envías:

addUser({
  name: "John",
  email: "john@example.com",
});

entonces el parámetro llamado

newUser

contendrá:

{
  name: "John",
  email: "john@example.com"
}

Ese objeto es el que se envía como cuerpo de la solicitud.

Comprensión de la URL

url: "users",

Dado que la URL base está configurada como:

https://jsonplaceholder.typicode.com/

RTK Query las combina automáticamente en:

https://jsonplaceholder.typicode.com/users

así que nunca tienes que escribir la dirección completa por tu cuenta.

Comprensión del método

method: "POST",

Esta línea indica explícitamente a RTK Query que envíe una solicitud POST. Si no se incluye, la solicitud usa GET por defecto.

Comprensión del cuerpo

body: newUser,

Lo que quiera que esté almacenado en newUser se envía como carga de la solicitud, por ejemplo:

{
  "name": "John",
  "email": "john@example.com"
}

El servidor recibe ese objeto tal como fue creado.

Paso 2: Exportar el gancho generado

export const {
  useAddUserMutation,
} = api;

Al igual que las consultas te proporcionan un gancho generado automáticamente como

useGetUsersQuery()

las mutaciones generan su propio gancho de forma automática:

useAddUserMutation()

Nunca escribes este gancho a mano: RTK Query lo construye por ti en función del nombre del endpoint.

Paso 3: Crear el componente React

Crea un archivo nuevo:

src/components/AddUser.jsx

y agrega este código:

import { useState } from "react";
import { useAddUserMutation } from "../services/api";const AddUser = () => {  const [name, setName] = useState("");
  const [email, setEmail] = useState("");  const [
    addUser,
    {
      isLoading,
      isSuccess,
      error,
    },
  ] = useAddUserMutation();  const handleSubmit = async (e) => {    e.preventDefault();    await addUser({
      name,
      email,
    });    setName("");
    setEmail("");  };  return (
    <form onSubmit={handleSubmit}>      <input
        type="text"
        placeholder="Enter Name"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />      <input
        type="email"
        placeholder="Enter Email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />      <button type="submit">
        Add User
      </button>      {isLoading && <p>Saving...</p>}      {isSuccess && <p>User Added Successfully.</p>}      {error && <p>Something went wrong.</p>}    </form>
  );};export default AddUser;

Analicemos qué está sucediendo aquí.

Comprensión de useAddUserMutation()

const [
  addUser,
  {
    isLoading,
    isSuccess,
    error,
  },
] = useAddUserMutation();

A diferencia de los ganchos de consulta, los ganchos de mutación devuelven un array en lugar de un objeto. El primer elemento:

addUser

Es la función que se llama para activar la solicitud, mientras que el segundo elemento es un objeto que contiene detalles útiles sobre el estado de dicha solicitud.

Comprensión de addUser()

await addUser({
  name,
  email,
});

Llamar a esta función envía una solicitud de la siguiente manera:

POST /users

que lleva un payload en formato JSON como este:

{
  "name": "John",
  "email": "john@example.com"
}

En el backend, ese payload se utiliza para crear un registro de usuario completamente nuevo.

Comprensión de los estados de mutación

Junto con la función desencadenante, RTK Query proporciona varios indicadores de estado que describen lo que está sucediendo con la solicitud.

isLoading

isLoading

Este indicador pasa a true mientras la mutación está en proceso, lo que lo hace ideal para desactivar un botón de envío o mostrar un spinner hasta que llegue la respuesta.

isSuccess

isSuccess

Una vez que la solicitud se completa sin errores, este valor pasa a ser true, lo que le brinda una señal clara para mostrar un mensaje de confirmación o redirigir al usuario a otra ubicación.

error

error

Si el servidor responde con un fallo, los detalles se muestran aquí, permitiéndole mostrar un error legible en lugar de una interfaz dañada.

Paso 4 — Renderizar el componente

Abra el archivo principal de la aplicación:

src/App.jsx

y reemplace su contenido por el siguiente:

import AddUser from "./components/AddUser";
function App() {
  return <AddUser />;
}export default App;

Luego inicie el servidor de desarrollo:

npm run dev

Rellene los campos del formulario y haga clic en Agregar usuario — RTK Query se encargará de enviar la solicitud POST por usted.

Flujo completo de la solicitud

A continuación, un resumen de lo que ocurre en el fondo, desde el envío del formulario hasta la actualización del estado:

User Fills Form
        │
        ▼
Clicks Submit
        │
        ▼
addUser()
        │
        ▼
Generated Mutation Hook
        │
        ▼
RTK Query
        │
        ▼
fetchBaseQuery()
        │
        ▼
POST Request
        │
        ▼
Server Response
        │
        ▼
Mutation State Updates
        │
        ▼
React Re-renders

Fíjese en todo lo que falta en este flujo:

  • fetch()
  • axios.post()
  • useEffect()
  • Estatus de carga controlado manualmente
  • Estatus de error controlado manualmente

RTK Query se encarga de todo esto en segundo plano.

builder.query() vs builder.mutation()

Saber cuándo utilizar cada uno de estos métodos del constructor es muy importante.

builder.query() está diseñado para obtener datos, generalmente a través de solicitudes GET, y genera hooks como useGetUsersQuery() que se ejecutan automáticamente tan pronto como se renderiza el componente. Por el contrario, builder.mutation() está destinado a modificar datos mediante métodos como POST, PUT, PATCH o DELETE. Produce hooks como useAddUserMutation() que solo se ejecutan cuando se llama explícitamente a la función desencadenante, en lugar de al renderizarse. En resumen, las consultas sirven para leer y las mutaciones para crear, actualizar o eliminar.

Elegir la herramienta adecuada para cada tarea mantiene la lógica de tu API coherente y fácil de comprender.

Mejores prácticas

Ten en cuenta estas pautas cada vez que construyas funcionalidades POST con RTK Query:

  • Utiliza builder.mutation() siempre que una operación modifique datos en el servidor.
  • Mantenga los cuerpos de las solicitudes ligeros, enviando solo los campos que realmente necesita el backend.
  • Tenga siempre en cuenta los valores de isLoading, isSuccess y error para que la interfaz sea receptiva e informativa.
  • Elija nombres descriptivos para los puntos de extremo, como addUser, createPost o registerUser.
  • Valide todo lo que el usuario haya escrito antes de enviarlo al servidor.
  • Considere utilizar unwrap() si prefiere manejar los casos de éxito y error con un bloque try...catch dentro de sus componentes.
  • Puntos clave

    Al seguir esta guía, ha aprendido cómo:

    • Configurar una mutación con builder.mutation().
    • Conectar un punto de extremo POST dentro de una API slice.
    • Enviar datos JSON a un servicio backend.
    • Utilice el gancho autogenerado useAddUserMutation().
    • Envíe una solicitud POST directamente desde un formulario de React.
    • Gestione los estados de carga, éxito y error sin código genérico manual.
    • Diferencie las consultas de las mutaciones.
    • Aplique prácticas sólidas para crear interacciones con APIs mantenibles.

    Este mismo patrón aparece constantemente en aplicaciones en producción: flujos de registro de usuarios, autenticación, publicación de artículos de blog, realización de pedidos y numerosos otros escenarios de creación de datos.

    ¿Qué sigue?

    Una vez que domine las solicitudes POST, el siguiente paso lógico es aprender a actualizar y eliminar registros existentes.

    La guía que viene a continuación abordará:

    • Actualización de registros con solicitudes PUT y PATCH.
    • Eliminación de registros mediante solicitudes DELETE.
    • Transmitir IDs dinámicos a los puntos finales de mutación.
    • Invalidar los datos en caché para que la interfaz de usuario se actualice automáticamente.
    • Utilizar etiquetas — providesTags y invalidatesTags — para mantener todo sincronizado sin necesidad de volver a cargar manualmente.

    Para cuando termines esa guía, estarás preparado para crear una aplicación completa CRUD utilizando patrones RTK Query listos para producción.

    Lecturas relacionadas