React Native Academy · Lektion

Persistens af Zustand-state med AsyncStorage

Pak en Zustand-store ind i persist-middleware understøttet af AsyncStorage, så state overlever genstart af appen, og håndtér tidspunktet for rehydrering.

Lektion 3 af 413 trin

Persistens af Zustand-state med AsyncStorage er en gratis React Native Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i React Native Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. React Native Academy-kurset indeholder 4 lektioner i alt.

Hvorfor gemme tilstand?

Som standard findes Zustand-tilstand kun i hukommelsen og går tabt, når appen lukkes. At gemme tilstand betyder, at den gemmes i enhedens lokale lager, så den overlever genstarter af appen. Det er afgørende for brugerpræferencer, godkendelsestokens, indkøbskurve eller andre data, som brugeren forventer stadig er der, når appen åbnes igen.

Installation af AsyncStorage

AsyncStorage er standard-API'et til nøgle-værdi-lager i React Native. I Expo managed workflow skal du installere community-pakken @react-native-async-storage/async-storage. Zustands indbyggede persist-middleware fungerer med alle lageradaptere, og AsyncStorage er det mest almindelige valg til mobilapps.

npx expo install @react-native-async-storage/async-storage

Tilføjelse af persist-middleware

Pak store-opretteren ind i persist, som importeres fra zustand/middleware. Giv den din store-fabrik og et konfigurationsobjekt med en name-nøgle (AsyncStorage-nøglen, hvor tilstanden gemmes) og en storage-nøgle (der peger på din AsyncStorage-adapter). Zustand håndterer automatisk læsning og skrivning.

import { create } from 'zustand';
import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';

export const useSettingsStore = create(
  persist<SettingsStore>(
    (set) => ({
      theme: 'light',
      notifications: true,
      setTheme: (theme) => set({ theme }),
      toggleNotifications: () =>
        set((state) => ({ notifications: !state.notifications })),
    }),
    {
      name: 'settings-store',
      storage: createJSONStorage(() => AsyncStorage),
    }
  )
);

Sådan fungerer persist internt

Når storet oprettes første gang, læser persist fra AsyncStorage og rehydrerer (gendanner) tidligere gemt tilstand, før den første komponent gengives. Når tilstanden ændres via set, serialiserer persist automatisk tilstanden til JSON og skriver den asynkront til AsyncStorage. Det hele sker uden ekstra kode i dine komponenter.

Håndtering af forsinkelsen ved rehydrering

Læsning fra AsyncStorage er asynkron, så storet ved den første gengivelse stadig kan indeholde den oprindelige tilstand, før rehydreringen er færdig. Zustands persist-middleware tilføjer flaget _hasHydrated og tilbagekaldet onFinishHydration. Brug dem til at vise en indlæsningsskærm, mens den gemte tilstand indlæses fra disken.

const hasHydrated = useSettingsStore((state) => state._hasHydrated);

if (!hasHydrated) {
  return <ActivityIndicator />; // Show loading until store is ready
}

// Alternatively, listen to hydration completion:
useEffect(() => {
  const unsub = useSettingsStore.persist.onFinishHydration(() => {
    setReady(true);
  });
  return unsub;
}, []);

Lagring af kun en del af tilstanden

Du ønsker ofte ikke at gemme alt i storet — for eksempel bør midlertidige indlæsningstilstande eller fejlmeddelelser ikke gemmes. Brug indstillingen partialize til at vælge, hvilke felter der skal gemmes. Det returnerede objekt indeholder kun de nøgler, du vil skrive til AsyncStorage.

persist<AuthStore>(
  (set) => ({
    user: null,
    token: null,
    isLoading: false,    // transient — don't persist
    error: null,         // transient — don't persist
    login: (user, token) => set({ user, token }),
    logout: () => set({ user: null, token: null }),
  }),
  {
    name: 'auth-store',
    storage: createJSONStorage(() => AsyncStorage),
    partialize: (state) => ({ user: state.user, token: state.token }),
  }
)

Versionering og migrering

Når du ændrer strukturen af din gemte tilstand i en ny appudgivelse, passer gamle data på brugernes enheder måske ikke til den nye form. Brug indstillingerne version og migrate til at opgradere gemt tilstand fra én version til den næste. Forøg version ved hver strukturel ændring, og håndtér den gamle tilstand i migrate-funktionen.

persist<SettingsStore>(
  (set) => ({ /* ... */ }),
  {
    name: 'settings-store',
    storage: createJSONStorage(() => AsyncStorage),
    version: 2,
    migrate: (persistedState: any, version: number) => {
      if (version === 1) {
        // Rename darkMode to theme in version 2
        persistedState.theme = persistedState.darkMode ? 'dark' : 'light';
        delete persistedState.darkMode;
      }
      return persistedState;
    },
  }
)

Rydning af gemt tilstand

Hvis du vil rydde den gemte tilstand — for eksempel når brugeren logger ud — skal du kalde useStore.persist.clearStorage(). Det fjerner dataene fra AsyncStorage. Du kan også kalde useStore.getState().reset() for samtidig at rydde tilstanden i hukommelsen. Hvis du gør begge dele, starter brugeren på en frisk ved næste appstart.

async function handleLogout() {
  // Clear in-memory state
  useAuthStore.getState().logout();

  // Clear persisted state from AsyncStorage
  await useAuthStore.persist.clearStorage();

  navigation.reset({ index: 0, routes: [{ name: 'Login' }] });
}

Brug af SecureStore til følsomme data

Til følsomme værdier som godkendelsestokens bør du foretrække Expo SecureStore frem for almindelig AsyncStorage. SecureStore bruger enhedens sikre enklave (iOS Keychain / Android Keystore) til at kryptere data, når de er gemt. Du kan oprette en brugerdefineret Zustand-lageradapter ved hjælp af SecureStores getItemAsync- og setItemAsync-metoder.

import * as SecureStore from 'expo-secure-store';

const secureStorage = {
  getItem: async (name: string) => await SecureStore.getItemAsync(name),
  setItem: async (name: string, value: string) =>
    await SecureStore.setItemAsync(name, value),
  removeItem: async (name: string) =>
    await SecureStore.deleteItemAsync(name),
};

// Use secureStorage instead of AsyncStorage:
storage: createJSONStorage(() => secureStorage),

Fejlfinding af gemt tilstand

Hvis du vil undersøge, hvad der er gemt i AsyncStorage under udviklingen, kan du kalde AsyncStorage.getAllKeys() og AsyncStorage.multiGet(keys) i udviklerkonsollen eller på en fejlfindingsskærm. Du kan også manuelt rydde forældede gemte data med AsyncStorage.clear(), når du tester migreringslogik. Test altid med en ny installation for at simulere virkelige scenarier ved opgradering af brugerens app.

// Debug helper — call from a dev-only screen
async function printStorage() {
  const keys = await AsyncStorage.getAllKeys();
  const pairs = await AsyncStorage.multiGet(keys);
  pairs.forEach(([key, value]) => {
    console.log(key, ':', JSON.parse(value ?? 'null'));
  });
}

Eksempel på lagring af et kurv-store

Her er et realistisk kurv-store, der gemmer sin liste over varer på tværs af appgenstarter. Indlæsnings- og fejltilstand er udeladt fra lagringen ved hjælp af partialize. total beregnes løbende i komponenten i stedet for at blive gemt, så den altid stemmer overens med varearrayet efter rehydrering.

export const useCartStore = create(
  persist<CartStore>(
    (set, get) => ({
      items: [],
      addItem: (item) => set((state) => ({ items: [...state.items, item] })),
      removeItem: (id) =>
        set((state) => ({ items: state.items.filter((i) => i.id !== id) })),
      clearCart: () => set({ items: [] }),
    }),
    {
      name: 'cart-store',
      storage: createJSONStorage(() => AsyncStorage),
      partialize: (state) => ({ items: state.items }),
    }
  )
);

Hurtigt tjek

Test din forståelse af begreberne inden for React Native Mobile Development fra denne lektion.

Opsummering af lektionen

I denne lektion har du lært, at persist-middleware pakker et Zustand-store ind for automatisk at gemme og gendanne tilstand fra AsyncStorage, at partialize styrer, hvilke felter der gemmes, så midlertidige indlæsnings- eller fejltilstande ikke gemmes, og at version sammen med migrate håndterer brud i tilstandens struktur på tværs af appopdateringer. Nu skal vi se på slices-mønstret og Devtools-integration i Zustand.

Gratis at komme i gang

Lær JavaScript med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
30
Lektioner
120

Ofte stillede spørgsmål

Er lektionen “Persistens af Zustand-state med AsyncStorage” gratis?

Ja — alle 3 lektioner i læringssporet React Native Academy, inklusive “Persistens af Zustand-state med AsyncStorage”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. React Native Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Persistens af Zustand-state med AsyncStorage”?

Pak en Zustand-store ind i persist-middleware understøttet af AsyncStorage, så state overlever genstart af appen, og håndtér tidspunktet for rehydrering. Du øver dig i React Native Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på React Native Academy?

Der kræves ingen tidligere erfaring. React Native Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “Persistens af Zustand-state med AsyncStorage”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne React Native Academy-lektion?

Ja. Alle React Native Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Oprettelse af en Zustand-store
  2. Læsning og opdatering af store-state i komponenter
  3. Persistens af Zustand-state med AsyncStorage
  4. Slices-mønsteret og DevTools-integration
← Tilbage til React Native Academy