การคงสถานะ Zustand ด้วย AsyncStorage
ครอบ Zustand store ด้วยมิดเดิลแวร์ persist ที่ใช้ AsyncStorage เป็นพื้นฐาน เพื่อให้สถานะคงอยู่หลังเปิดแอปใหม่ และจัดการจังหวะการกู้คืนสถานะ
การคงสถานะ Zustand ด้วย AsyncStorage เป็นบทเรียน React Native Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน React Native Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน
บางส่วนของบทเรียนนี้ยังไม่ได้รับการแปล และแสดงเป็นภาษาอังกฤษ
Why Persist State?
By default, Zustand state lives only in memory and is lost when the app closes. Persisting state means saving it to the device's local storage so it survives app restarts. This is essential for user preferences, authentication tokens, shopping carts, or any data the user expects to still be there when they reopen the app.
Installing AsyncStorage
AsyncStorage is the standard key-value storage API for React Native. In Expo managed workflow, install the community package @react-native-async-storage/async-storage. Zustand's built-in persist middleware works with any storage adapter, and AsyncStorage is the most common choice for mobile apps.
npx expo install @react-native-async-storage/async-storageAdding the persist Middleware
Wrap the store creator with persist imported from zustand/middleware. Pass it your store factory and a configuration object with a name key (the AsyncStorage key where state will be saved) and a storage key (pointing to your AsyncStorage adapter). Zustand handles reading and writing automatically.
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),
}
)
);How Persist Works Internally
When the store is first created, persist reads from AsyncStorage and rehydrates (restores) any previously saved state before rendering the first component. When state changes via set, persist automatically serializes the state to JSON and writes it to AsyncStorage asynchronously. This all happens without any extra code in your components.
Handling the Rehydration Delay
AsyncStorage reads are asynchronous, so on the first render the store may still contain the initial state before rehydration finishes. Zustand's persist middleware adds a _hasHydrated flag and an onFinishHydration callback. Use these to show a loading screen while persisted state is loading from disk.
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;
}, []);Persisting Only Part of the State
You often do not want to persist everything in the store — for example, transient loading states or error messages should not be saved. Use the partialize option to select which fields to persist. The returned object contains only the keys you want to write to 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 }),
}
)Versioning and Migration
When you change the structure of your persisted state in a new app release, old data on users' devices may not match the new shape. Use the version and migrate options to upgrade stored state from one version to the next. Increment version with each structural change and handle old state in the migrate function.
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;
},
}
)Clearing Persisted State
To clear the persisted state — for example when the user logs out — call useStore.persist.clearStorage(). This removes the data from AsyncStorage. You can also call useStore.getState().reset() to clear the in-memory state at the same time. Doing both ensures the user starts fresh on the next app launch.
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' }] });
}Using SecureStore for Sensitive Data
For sensitive values like auth tokens, prefer Expo SecureStore over plain AsyncStorage. SecureStore uses the device's secure enclave (iOS Keychain / Android Keystore) to encrypt data at rest. You can create a custom Zustand storage adapter using SecureStore's getItemAsync and setItemAsync methods.
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),Debugging Persisted State
To inspect what is stored in AsyncStorage during development, call AsyncStorage.getAllKeys() and AsyncStorage.multiGet(keys) in the dev console or a debug screen. You can also manually clear stale persisted state with AsyncStorage.clear() when testing migration logic. Always test with a fresh install to simulate real user upgrade scenarios.
// 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'));
});
}Persisting a Cart Store Example
Here is a realistic cart store that persists its items list across app restarts. Loading and error state are excluded from persistence using partialize. The total is derived on the fly in the component rather than stored, so it is always consistent with the items array after rehydration.
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 }),
}
)
);Quick Check
Test your understanding of React Native Mobile Development concepts from this lesson.
Lesson Recap
In this lesson you learned: the persist middleware wraps a Zustand store to save and restore state from AsyncStorage automatically, partialize controls which fields are persisted to avoid saving transient loading or error state, and version with migrate handles breaking state shape changes across app updates. Next up we explore the slices pattern and Devtools integration in Zustand.
คำถามที่พบบ่อย
บทเรียน “การคงสถานะ Zustand ด้วย AsyncStorage” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การคงสถานะ Zustand ด้วย AsyncStorage” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส React Native Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส React Native Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การคงสถานะ Zustand ด้วย AsyncStorage”
ครอบ Zustand store ด้วยมิดเดิลแวร์ persist ที่ใช้ AsyncStorage เป็นพื้นฐาน เพื่อให้สถานะคงอยู่หลังเปิดแอปใหม่ และจัดการจังหวะการกู้คืนสถานะ คุณปฏิบัติ React Native Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน React Native Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน React Native Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การคงสถานะ Zustand ด้วย AsyncStorage” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน React Native Academy นี้ได้ไหม
ได้ บทเรียน React Native Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การสร้าง Zustand Store
- การอ่านและอัปเดตสถานะ Store ในคอมโพเนนต์
- การคงสถานะ Zustand ด้วย AsyncStorage
- รูปแบบ Slices และการผสานรวม Devtools