Wysyłanie danych za pomocą zapytania RTK: Praktyczny przewodnik po mutacjach
Dowiedz się, jak używać builder.mutation() w RTK Query do wysyłania zapytań POST, zarządzania stanami ładowania i błędów oraz tworzenia działającego komponentu formularza.
Wprowadzenie
Wcześniej omówiliśmy, jak skonfigurować Redux Toolkit Query (RTK Query) i wykonywać operacje odczytu za pomocą builder.query(). Dzięki temu mogliśmy pobrać dane z API i wyświetlić je w aplikacji React bez konieczności ręcznego tworzenia funkcji useEffect(), useState() czy specjalistycznej logiki pobierania danych.
Jednak odczyt danych to tylko połowa rozwiązania przy pracy z API. Większość aplikacji wymaga również sposobów na dodawanie, modyfikowanie lub usuwanie rekordów na serwerze.
Rozważmy kilka typowych scenariuszy:
- Formularz rejestracyjny wysyła nowe dane konta.
- Ekran logowania przesyła dane uwierzytelniające w celu weryfikacji.
- Płytforma blogowa publikuje nowe artykuły.
- Sklep internetowy realizuje nowe zamówienia.
- Aplikacja do zarządzania zadaniami przechowuje nowo dodane zadania.
Każda z tych operacji przesyła informacje od klienta do serwera, a zwykle odbywa się to poprzez żądanie HTTP POST.
RTK Query nie traktuje wywołań POST jako zapytań — traktuje je jako mutacje.
W tym artykule omówimy wysyłanie danych za pomocą builder.mutation(). Przeanalizujemy każdy fragment kodu oraz każdą ustawienie konfiguracyjne, abyś zrozumiał nie tylko to, co należy wpisać, ale także dlaczego każda część ma znaczenie.
Rozumienie metod HTTP
Zanim przejdziemy do kodu, przydatne jest zapoznanie się z różnymi czasownikami HTTP i ich przeznaczeniem.
Typowa REST API udostępnia kilka operacji:
| Metoda | Cel | Przykład |
|---|---|---|
| GET | Czytanie danych | Pobranie wszystkich użytkowników |
| POST | Dodawanie nowych danych |
To przewodnik skupia się na metodzie POST, która służy do tworzenia nowych zasobów na serwerze.
Dlaczego POST nie używa builder.query()?
To częsty punkt zamieszania dla początkujących.
Skoro builder.query() może pobierać dane, dlaczego ta sama funkcja nie może wysyłać danych na serwer?
Powód leży w przeznaczeniu każdego narzędzia.
Zapytania
Zapytania służą do pobierania informacji.
Typowe przykłady:
- Pobierz użytkowników
- Pobierz produkty
- Pobierz zamówienia
- Pobierz wpisy
Ponieważ te same dane mogą być żądane wielokrotnie, zapytania automatycznie przechowują w pamięci ich wyniki.
Mutacje
Mutacje służą do modyfikacji danych.
Typowe przykłady:
- Stworzenie użytkownika
- Zaktualizowanie użytkownika
- Usunięcie użytkownika
- Zalogowanie
- Rejestracja
Mutacja sygnalizuje serwerowi, że coś musi ulec zmianie.
Dzięki temu rozróżnieniu RTK Query obsługuje mutacje oddzielnie od zwykłych zapytań.
To, co zamierzamy stworzyć
Zbudujemy prosty formularz, który przesyła nowego użytkownika do serwera.
Celowy endpoint to:
https://jsonplaceholder.typicode.com/users
A treść przesyłana w ciele żądania będzie wyglądać tak:
{
"name": "John Doe",
"email": "john@example.com"
}
Struktura projektu
src
│
├── app
│ └── store.js
│
├── services
│ └── api.js
│
├── components
│ └── AddUser.jsx
│
├── App.jsx
│
└── main.jsx
Konfiguracja sklepu Redux pozostaje taka sama jak wcześniej. Wszystko, co musimy dodać, to punkt końcowy do mutacji oraz komponent obsługujący wysyłkę formularza.
Krok 1 — Stworzenie punktu końcowego do mutacji
Otwórz plik usługi API:
src/services/api.js
Następnie dodaj nową definicję punktu końcowego wewnątrz obiektu 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;
Przeanalizujmy to wers po wersie.
Rozumienie builder.mutation()
addUser: builder.mutation({
Chociaż builder.query() służy do pobierania danych, builder.mutation() jest używany wtedy, gdy potrzebujemy coś zmienić na serwerze.
Powszechne scenariusze jego zastosowania:
- Tworzenie użytkowników
- Rегистrowanie kont
- Logowanie się
- Aktualizacja produktów
- Usuwanie postów
Za każdym razem, gdy twoja aplikacja zapisuje lub zmienia dane w tle, mutacja jest odpowiednim narzędziem.
Rozumienie query()
query: (newUser) => ({
Funkcja ta otrzymuje wszystkie dane, które przekazujesz jej z kodu React.
Na przykład, jeśli wyślesz:
addUser({
name: "John",
email: "john@example.com",
});
wtedy parametr o nazwie
newUser
będzie zawierał:
{
name: "John",
email: "john@example.com"
}
To obiekt jest wysyłany jako ciało żądania.
Rozumienie URL
url: "users",
Biorąc pod uwagę, że adres bazowy jest skonfigurowany jako:
https://jsonplaceholder.typicode.com/
RTK Query łączy je automatycznie w:
https://jsonplaceholder.typicode.com/users
dlatego nie musisz samodzielnie wpisywać pełnego adresu.
Rozumienie metody
method: "POST",
To zdanie wyraźnie instruuje RTK Query o wysłaniu żądania POST. Jeśli go pominiesz, żądanie domyślnie użyje metody GET.
Rozumienie ciała żądania
body: newUser,
Wszystko, co jest przechowywane w newUser, jest przekazywane jako treść żądania, na przykład:
{
"name": "John",
"email": "john@example.com"
}
Serwer otrzymuje ten obiekt dokładnie w takiej formie, w jakiej został utworzony.
Krok 2 — Eksportowanie wygenerowanego hooka
export const {
useAddUserMutation,
} = api;
Tak samo jak zapytania dają automatycznie wygenerowany hook, tak
useGetUsersQuery()
mutacje automatycznie tworzą swój własny hook:
useAddUserMutation()
Nigdy nie piszesz tego hooka ręcznie — RTK Query buduje go dla ciebie na podstawie nazwy endpointu.
Krok 3 — Tworzenie komponentu React
Stwórz nowy plik:
src/components/AddUser.jsx
i dodaj ten kod:
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;
Rozbierzmy to, co się tutaj dzieje.
Zrozumienie useAddUserMutation()
const [
addUser,
{
isLoading,
isSuccess,
error,
},
] = useAddUserMutation();
Inaczej niż hooki zapytań, hooki mutacji zwracają tablicę zamiast obiektu. Pierwszy element:
addUser
To funkcja, którą wywołujesz, aby uruchomić żądanie, natomiast drugi element to obiekt zawierający przydatne informacje o stanie tego żądania.
Rozumienie addUser()
await addUser({
name,
email,
});
Wywołanie tej funkcji wysyła żądanie w następujący sposób:
POST /users
z ładunkiem w formacie JSON wyglądającym w ten sposób:
{
"name": "John",
"email": "john@example.com"
}
W warstwie backendowej ten ładunek jest używany do utworzenia zupełnie nowego rekordu użytkownika.
Rozumienie stanów mutacji
Oprócz funkcji uruchamiającej, RTK Query dostarcza kilka flag stanu opisujących to, co dzieje się z żądaniem.
isLoading
isLoading
Ta flaga przyjmuje wartość true, gdy mutacja jest w trakcie wykonywania, co sprawia, że doskonale nadaje się do wyłączania przycisku wysyłki lub pokazywania ikony spinującej, dopóki nie nadejdzie odpowiedź.
isSuccess
isSuccess
Gdy żądanie zostanie zakończone bez błędów, wartość ta staje się true, co daje wyraźny sygnał do pokazania komunikatu potwierdzenia lub przekierowania użytkownika w inne miejsce.
error
error
Jeśli serwer odpowie o błędzie, szczegóły trafiają tutaj, umożliwiając wyświetlenie czytelnego komunikatu o błędzie zamiast uszkodzonego interfejsu.
Krok 4 — Wyświetlenie komponentu
Otwórz główny plik aplikacji:
src/App.jsx
i zastąp jego zawartość następującym tekstem:
import AddUser from "./components/AddUser";
function App() {
return <AddUser />;
}export default App;
Następnie uruchom serwer deweloperski:
npm run dev
Wypełnij pola formularza i naciśnij Add User — RTK Query samodzielnie wysyła żądanie POST.
Pełny przepływ żądań
Oto streszczenie tego, co dzieje się w tle, od wysłania formularza do aktualizacji stanu:
User Fills Form
│
▼
Clicks Submit
│
▼
addUser()
│
▼
Generated Mutation Hook
│
▼
RTK Query
│
▼
fetchBaseQuery()
│
▼
POST Request
│
▼
Server Response
│
▼
Mutation State Updates
│
▼
React Re-renders
Zwróć uwagę na wszystko, czego brakuje w tym procesie:
fetch()axios.post()useEffect()- Ręczne śledzenie stanu ładowania
- Ręczne śledzenie stanu błędu
RTK Query zajmuje się każdym z tych elementów w tle.
builder.query() vs builder.mutation()
Bardzo ważne jest, by wiedzieć, kiedy używać poszczególnych metod buildera.
builder.query() służy do pobierania danych, zazwyczaj za pomocą żądań GET, i generuje hooki takie jak useGetUsersQuery(), które uruchamiają się automatycznie po renderowaniu komponentu. builder.mutation() natomiast służy do modyfikowania danych za pomocą metod takich jak POST, PUT, PATCH lub DELETE. Tworzy on hooki takie jak useAddUserMutation(), które uruchamiają się tylko wtedy, gdy wyraźnie wezwiesz funkcję aktywującą, a nie przy renderowaniu. Krótko mówiąc, zapytania służą do odczytu, a mutacje do tworzenia, aktualizowania lub usuwania.
Wybór odpowiedniego narzędzia do każdego zadań zapewnia spójność logiki API i ułatwia jej zrozumienie.
Najlepsze praktyki
Pamiętaj o tych wytycznych przy tworzeniu funkcjonalności POST z użyciem RTK Query:
- Używaj
builder.mutation(), gdy operacja modyfikuje dane na serwerze.
isLoading, isSuccess oraz error, aby interfejs wydawał się responsywny i dostarczający wystarczających informacji.addUser, createPost lub registerUser.unwrap(), jeśli wolisz obsługiwać przypadki sukcesu i niepowodzenia za pomocą bloku try...catch w swoich komponentach.Główne wnioski
Pracując z tym przewodnikiem, nauczyłeś się, jak:
- Ustawić mutację za pomocą
builder.mutation(). - Podłączyć punkt końcowy typu POST w ramach API slice.
- Wysłać dane JSON do usługi backendowej.
- Skorzystaj z automatycznie generowanego hooka
useAddUserMutation(). - Rozpocznij żądanie POST bezpośrednio z formularza React.
- Zarządzaj stanami ładowania, sukcesu i błędów bez konieczności pisania własnego kodu szablonowego.
- Rozróżnij zapytania od mutacji.
- Zastosuj sprawdzone praktyki przy tworzeniu interakcji z API, które są łatwe w utrzymaniu.
To samo wzorcę występuje ciągle w aplikacjach produkcyjnych — procesy rejestracji użytkowników, autoryzacja, publikowanie postów na blogu, składanie zamówień oraz niezliczone inne scenariusze tworzenia danych.
Co dalej?
Gdy już opanujesz żądania POST, naturalnym następnym krokiem jest nauczenie się aktualizacji i usuwania istniejących rekordów.
Nadchodzący przewodnik omówi:
- Aktualizację rekordów za pomocą żądań PUT i PATCH.
- Usuwanie rekordów za pomocą żądań DELETE.
- Przekazywanie dynamicznych ID do punktów końcowych mutacji.
- Anulowanie danych z pamięci podręcznej, aby interfejs użytkownika automatycznie się odświeżył.
- Użycie tagów —
providesTagsiinvalidatesTags— aby utrzymać wszystko w synchronizacji bez konieczności ręcznego ponownego pobierania danych.
Gdy skończysz tę przewodnik, będziesz w stanie stworzyć pełną aplikację CRUD przy użyciu gotowych do produkcji wzorców RTK Query.
Literatura pokrewna
- Zmiany domyślnych ustawień w TypeScript 6.0: Praktyczny przewodnik migracji — Dowiedz się, które dziewięć domyślnych ustawień kompilatora TypeScript 6.0 uległo zmianie, jak skonfigurować tsconfig na rok 2026 oraz jak przygotować bazy kodu pod TypeScript 7 oparty na Go.
- Standardy Full-Stack JavaScript w 2026 roku: TypeScript, RSC i inne — Wyjaśnia, dlaczego TypeScript, React Server Components oraz bardziej efektywne podejścia do zarządzania stanem stały się standardowym zestawem narzędzi dla zespołów pracujących z JavaScriptem w 2026 roku.