React Native Academy · leksjon

Mutasjoner med useMutation og ugyldiggjøring av hurtigbuffer

Bruk useMutation til å POST-e data, ugyldiggjør relaterte spørringer ved suksess slik at listen oppdateres automatisk, og vis optimistisk tilbakemelding i brukergrensesnittet mens forespørselen behandles.

Leksjon 2 av 413 trinn

Mutasjoner med useMutation og ugyldiggjøring av hurtigbuffer er en gratis leksjon i React Native Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i React Native Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i React Native Academy inneholder totalt 4 leksjoner.

Hva er en mutasjon?

I React Query-terminologien er en mutasjon enhver operasjon som endrer serverdata — forespørsler med POST, PUT, PATCH eller DELETE. Mens useQuery henter og hurtigbufrer data, håndterer useMutation endringer av data med tilstander for lasting, feil og vellykket resultat, samt kraftige tilbakekallingsfunksjoner for sideeffekter.

Å skille spørringer (lesing) fra mutasjoner (skriving) er et viktig konseptuelt mønster. Mutasjoner hurtigbufrer ikke resultatene sine — de utløser sideeffekter og får deretter relaterte spørringer til å hente ferske data på nytt.

Grunnleggende om useMutation

useMutation tar imot en mutationFn — en asynkron funksjon som utfører skriveoperasjonen. Den returnerer en mutate-funksjon (eller mutateAsync for Promise-basert bruk) som De kaller når brukeren utløser handlingen.

I motsetning til useQuery kjører ikke mutasjoner automatisk. De venter til De kaller mutate(variables). Hooken gir tilgang til tilstandene isPending, isError, isSuccess, error og data fra mutasjonens svar.

import { useMutation } from '@tanstack/react-query';

async function createPost(newPost) {
  const response = await fetch('https://api.example.com/posts', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(newPost),
  });
  if (!response.ok) throw new Error('Failed to create post');
  return response.json();
}

const { mutate, isPending, isError } = useMutation({
  mutationFn: createPost,
});

Kalle mutate og mutateAsync

Kall mutate(variables) for å utløse mutasjonen. Argumentet variables sendes direkte til mutationFn. mutate starter operasjonen uten å vente — den returnerer ikke en Promise. Bruk hookens onSuccess- og onError-tilbakekallinger til å reagere på resultatet.

Bruk mutateAsync(variables) i stedet når De må vente på resultatet i en asynkron funksjon (for eksempel for å navigere etter et vellykket innlegg). Pakk alltid mutateAsync inn i try/catch — ubehandlede avvisninger vil føre til feil.

const { mutate, mutateAsync, isPending } = useMutation({
  mutationFn: createPost,
});

// Using mutate (fire-and-forget):
function handleSubmit() {
  mutate({ title: 'My Post', body: postContent });
}

// Using mutateAsync (awaitable):
async function handleSubmitAndNavigate() {
  try {
    const newPost = await mutateAsync({ title: 'My Post', body: postContent });
    navigation.navigate('PostDetail', { id: newPost.id });
  } catch (err) {
    Alert.alert('Error', err.message);
  }
}

onSuccess: Tilbakekalling etter mutasjon

onSuccess-tilbakekallingen utløses når mutasjonen fullføres. Den mottar resultatdataene fra mutasjonen og variablene som ble sendt til mutate. Bruk onSuccess til å ugyldiggjøre relaterte spørringer, vise en bekreftelse på at operasjonen lyktes, tilbakestille skjemaer eller navigere bort.

De kan definere onSuccess på hook-nivået (for logikk som alltid skal gjelde) og også sende den som det andre argumentet til mutate(variables, { onSuccess }) for tilpasning per kall.

import { useMutation, useQueryClient } from '@tanstack/react-query';

const queryClient = useQueryClient();

const { mutate } = useMutation({
  mutationFn: createPost,
  onSuccess: (newPost, variables) => {
    // Refresh the posts list:
    queryClient.invalidateQueries({ queryKey: ['posts'] });
    // Show success:
    Alert.alert('Post created!', newPost.title);
    // Reset form:
    resetForm();
  },
  onError: (error) => {
    Alert.alert('Error', error.message);
  },
});

Ugyldiggjøre hurtigbufferet etter en mutasjon

Ugyldiggjøring av hurtigbufferet er prosessen med å merke hurtigbufrede spørringer som foreldede etter en mutasjon, slik at de henter ferske data på nytt. Bruk queryClient.invalidateQueries sammen med en spørringsnøkkel. Delvis samsvar med nøkler støttes — ugyldiggjøring av ['posts'] ugyldiggjør alle spørringer der nøkkelen begynner med ['posts'], inkludert ['posts', userId].

Ugyldiggjøring utløser bakgrunnsforespørsler på nytt for alle aktive (monterte) spørringer med samsvarende nøkler. Komponenter som bruker disse spørringene, viser ferske data i løpet av én tur-retur til nettverket.

const { mutate: deletePost } = useMutation({
  mutationFn: (postId) =>
    fetch('/api/posts/' + postId, { method: 'DELETE' }),
  onSuccess: (data, postId) => {
    // Invalidate the posts list:
    queryClient.invalidateQueries({ queryKey: ['posts'] });
    // Also invalidate the specific post's cache:
    queryClient.invalidateQueries({ queryKey: ['post', postId] });
  },
});

Optimistiske oppdateringer

Optimistiske oppdateringer oppdaterer brukergrensesnittet umiddelbart før serveren har bekreftet mutasjonen. Hvis mutasjonen lykkes, bekreftes den antatte endringen. Hvis den mislykkes, tilbakestilles brukergrensesnittet til den forrige tilstanden. Dette gjør at samhandling føles umiddelbar — De slipper å vente på serveren.

Implementer optimistiske oppdateringer i onMutate: lagre et øyeblikksbilde av den gjeldende hurtigbufferen, oppdater hurtigbufferet umiddelbart, og rull deretter tilbake i onError ved behov. React Query tilbyr queryClient.setQueryData for manuell oppdatering av hurtigbufferet.

const { mutate: likePost } = useMutation({
  mutationFn: (postId) => fetch('/api/posts/' + postId + '/like', { method: 'POST' }),
  onMutate: async (postId) => {
    await queryClient.cancelQueries({ queryKey: ['posts'] });
    const snapshot = queryClient.getQueryData(['posts']);
    // Optimistically add like:
    queryClient.setQueryData(['posts'], (old) =>
      old.map(p => p.id === postId ? { ...p, likes: p.likes + 1 } : p)
    );
    return { snapshot }; // return for rollback
  },
  onError: (err, postId, context) => {
    queryClient.setQueryData(['posts'], context.snapshot); // rollback
  },
});

Mutasjonsstatus og tilbakemeldinger i brukergrensesnittet

Bruk statusfeltene for mutasjonen til å gi passende tilbakemeldinger i brukergrensesnittet. isPending er true mens mutasjonen pågår — deaktiver send-knappen og vis en spinner. isSuccess er true etter fullføring — vis en bekreftelse. isError er true hvis mutasjonen mislyktes — vis feilmeldingen.

React Query tilbakestiller mutasjonsstatusen automatisk etter en konfigurerbar periode angitt av gcTime. Hvis De vil tilbakestille den manuelt (for eksempel for å la brukeren prøve på nytt), kan De kalle funksjonen reset() som hooken returnerer.

const { mutate, isPending, isError, isSuccess, error, reset } = useMutation({
  mutationFn: submitForm,
});

return (
  <View>
    <TextInput value={text} onChangeText={setText} editable={!isPending} />
    <Button
      title={isPending ? 'Submitting...' : 'Submit'}
      onPress={() => mutate({ text })}
      disabled={isPending}
    />
    {isError && <Text style={{ color: 'red' }}>{error.message}</Text>}
    {isSuccess && <Text style={{ color: 'green' }}>Saved!</Text>}
  </View>
);

Oppdatere hurtigbufferet direkte etter en mutasjon

I stedet for å ugyldiggjøre og hente data på nytt kan De oppdatere hurtigbufferet direkte med mutasjonssvaret ved å bruke queryClient.setQueryData. Dette er mer effektivt når serveren returnerer de oppdaterte dataene i mutasjonssvaret — De kan legge dem til i listen uten en ekstra nettverksforespørsel.

Dette mønsteret — å sette hurtigbufferet fra serversvaret i stedet for å ugyldiggjøre det — sparer en tur-retur til nettverket og er nyttig for lister der De vil legge til det nye elementet umiddelbart.

const { mutate } = useMutation({
  mutationFn: createPost,
  onSuccess: (newPost) => {
    // Append new post to cached list directly:
    queryClient.setQueryData(['posts'], (oldPosts) => {
      if (!oldPosts) return [newPost];
      return [newPost, ...oldPosts]; // prepend new post
    });
    // No invalidation needed — cache is already up to date!
  },
});

Globale mutasjonstilbakekallinger via QueryClient

De kan definere globale mutasjonstilbakekallinger i defaultOptions.mutations i QueryClient for logging, feilrapportering eller tokenfornyelse som skal gjelde for alle mutasjoner i appen. Lokale mutasjonsalternativer overstyrer globale alternativer — begge kan eksistere samtidig.

Et vanlig bruksområde er en global onError-tilbakekalling som kontrollerer om svaret er 401 Unauthorized, og utløser en utloggings- eller tokenfornyelsesflyt for hver mutasjon uten at denne logikken må gjentas i hvert enkelt useMutation-kall.

const queryClient = new QueryClient({
  defaultOptions: {
    mutations: {
      onError: (error) => {
        // Global error handling for all mutations:
        if (error.status === 401) {
          handleUnauthorized();
        } else {
          console.error('Mutation error:', error.message);
        }
      },
    },
  },
});

Mutasjoner med filopplastinger

Mutasjoner håndterer filopplastinger ved å ta imot FormData som variablene. mutationFn oppretter et FormData-objekt og sender det med fetch ved å bruke innholdstypen multipart/form-data. React Query håndterer laste- og feiltilstanden på samme måte som for alle andre mutasjoner.

For store filopplastinger kan De følge fremdriften ved å bruke en egendefinert fetch-wrapper med XHR og lagre fremdriften i en separat tilstandsvariabel som oppdateres ved hjelp av onUploadProgress-mønsteret.

const { mutate: uploadPhoto, isPending } = useMutation({
  mutationFn: async ({ uri, userId }) => {
    const formData = new FormData();
    formData.append('photo', {
      uri,
      type: 'image/jpeg',
      name: 'photo.jpg',
    });
    formData.append('userId', userId);

    const response = await fetch('/api/photos', {
      method: 'POST',
      body: formData,
      // Do NOT set Content-Type — let fetch set multipart boundary
    });
    return response.json();
  },
  onSuccess: () => queryClient.invalidateQueries({ queryKey: ['photos'] }),
});

Kjede mutasjoner

For arbeidsflyter som krever flere sekvensielle serveroperasjoner (for eksempel å opprette en ordre og deretter behandle betalingen) kan De kjede mutasjoner ved å bruke mutateAsync i rekkefølge. Hver mutasjon kan bruke resultatet fra den forrige som inndata. Pakk kjeden inn i try/catch for feilhåndtering.

Hvis mellomliggende trinn mislykkes, kan det hende De må rulle tilbake tidligere trinn manuelt eller utløse kompenserende transaksjoner. Utform API-et for atomisitet når det er mulig, slik at gjenoppretting etter feil på klientsiden blir enklere.

const { mutateAsync: createOrder } = useMutation({ mutationFn: apiCreateOrder });
const { mutateAsync: processPayment } = useMutation({ mutationFn: apiProcessPayment });

async function handleCheckout(cartData, paymentInfo) {
  try {
    const order = await createOrder(cartData);
    const payment = await processPayment({ orderId: order.id, ...paymentInfo });
    queryClient.invalidateQueries({ queryKey: ['orders'] });
    navigation.navigate('OrderConfirmation', { orderId: order.id });
  } catch (error) {
    Alert.alert('Checkout failed', error.message);
  }
}

Kort test

Test forståelsen Deres av konseptene innen React Native Mobile Development fra denne leksjonen.

Oppsummering av leksjonen

I denne leksjonen har De lært at: useMutation håndterer skriveoperasjoner (POST/PUT/DELETE) med tilstandene isPending, isError og isSuccess, onSuccess er det primære stedet å kalle queryClient.invalidateQueries for å oppdatere relaterte hurtigbufrede data, og optimistiske oppdateringer via onMutate oppdaterer hurtigbufferet umiddelbart og lagrer et øyeblikksbilde for tilbakerulling hvis serverforespørselen mislykkes. Neste steg er å lagre React Query-hurtigbufferet i AsyncStorage for en offline-først-opplevelse.

Gratis å komme i gang

Lær deg JavaScript med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
30
Leksjoner
120

Ofte stilte spørsmål

Er leksjonen «Mutasjoner med useMutation og ugyldiggjøring av hurtigbuffer» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien React Native Academy, inkludert «Mutasjoner med useMutation og ugyldiggjøring av hurtigbuffer», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i React Native Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Mutasjoner med useMutation og ugyldiggjøring av hurtigbuffer»?

Bruk useMutation til å POST-e data, ugyldiggjør relaterte spørringer ved suksess slik at listen oppdateres automatisk, og vis optimistisk tilbakemelding i brukergrensesnittet mens forespørselen behan… Du øver på React Native Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med React Native Academy?

Ingen tidligere erfaring er nødvendig. React Native Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.

Hvor lang tid tar leksjonen «Mutasjoner med useMutation og ugyldiggjøring av hurtigbuffer»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne React Native Academy-leksjonen?

Ja. Alle React Native Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. QueryClient, QueryClientProvider og useQuery
  2. Mutasjoner med useMutation og ugyldiggjøring av hurtigbuffer
  3. Bevare spørringshurtigbufferet med AsyncStorage
  4. Konfigurere bakgrunnshenting og stale time
← Tilbake til React Native Academy