普通视图

发现新文章,点击刷新页面。
昨天 — 2026年1月12日首页

Zustand 入门:React Native 状态管理的正确用法

作者 wayne214
2026年1月12日 08:34

一、Zustand 是什么,适合什么场景

Zustand 是一个轻量级、基于 hooks 的状态管理库,核心特点是:

  • 无 Provider(无需 Context 包裹)
  • API 极简(create + hooks)
  • 按需订阅(避免无关组件重渲染)
  • 对 React Native 友好(无额外平台依赖)
  • 可渐进式引入

非常适合以下 RN 场景:

  • 中小规模应用
  • RN Hybrid / Module 化工程
  • UI 状态 + 业务状态混合管理
  • 替代部分 Redux 的场景

二、安装

yarn add zustand
# 或
npm install zustand

React Native 无需额外配置。


三、最基础用法(核心必会)

1. 创建 Store

// store/useCounterStore.ts
import { create } from 'zustand';

type CounterState = {
  count: number;
  inc: () => void;
  dec: () => void;
};

export const useCounterStore = create<CounterState>((set) => ({
  count: 0,
  inc: () => set((state) => ({ count: state.count + 1 })),
  dec: () => set((state) => ({ count: state.count - 1 })),
}));

2. 在组件中使用

import React from 'react';
import { View, Text, Button } from 'react-native';
import { useCounterStore } from './store/useCounterStore';

export default function Counter() {
  const count = useCounterStore((state) => state.count);
  const inc = useCounterStore((state) => state.inc);

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="+" onPress={inc} />
    </View>
  );
}

关键点

  • selector 模式useStore(state => state.xxx)
  • 只订阅使用到的字段,避免全量刷新

四、推荐的工程化写法(重要)

❌ 不推荐

const store = useStore();

这样会导致任意状态变更都触发重渲染


✅ 推荐:拆分 selector

const count = useCounterStore((s) => s.count);
const inc = useCounterStore((s) => s.inc);

或:

const { count, inc } = useCounterStore(
  (s) => ({ count: s.count, inc: s.inc })
);

五、Zustand 在 React Native 中的常见模式

1. 全局 UI 状态(Loading / Modal)

type UIState = {
  loading: boolean;
  showLoading: () => void;
  hideLoading: () => void;
};

export const useUIStore = create<UIState>((set) => ({
  loading: false,
  showLoading: () => set({ loading: true }),
  hideLoading: () => set({ loading: false }),
}));
const loading = useUIStore((s) => s.loading);

2. 业务状态(登录信息)

type User = {
  id: string;
  name: string;
};

type AuthState = {
  user?: User;
  login: (u: User) => void;
  logout: () => void;
};

export const useAuthStore = create<AuthState>((set) => ({
  user: undefined,
  login: (user) => set({ user }),
  logout: () => set({ user: undefined }),
}));

3. 异步 Action(非常自然)

type ListState = {
  list: string[];
  loading: boolean;
  fetchList: () => Promise<void>;
};

export const useListStore = create<ListState>((set) => ({
  list: [],
  loading: false,
  fetchList: async () => {
    set({ loading: true });
    const res = await fetch('https://example.com/list');
    const data = await res.json();
    set({ list: data, loading: false });
  },
}));

RN 中无需 thunk / saga。


六、性能优化(RN 场景非常关键)

1. 使用 shallow 避免对象对比

import { shallow } from 'zustand/shallow';

const { count, inc } = useCounterStore(
  (s) => ({ count: s.count, inc: s.inc }),
  shallow
);

2. 将高频 UI 状态拆分 Store

store/
 ├── useAuthStore.ts
 ├── useUIStore.ts
 ├── useListStore.ts

避免一个大 Store。


七、持久化(AsyncStorage)

RN 常用:zustand + persist

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

export const useAuthStore = create(
  persist(
    (set) => ({
      token: '',
      setToken: (token: string) => set({ token }),
      clearToken: () => set({ token: '' }),
    }),
    {
      name: 'auth-storage',
      storage: {
        getItem: AsyncStorage.getItem,
        setItem: AsyncStorage.setItem,
        removeItem: AsyncStorage.removeItem,
      },
    }
  )
);

八、Zustand vs Redux Toolkit(RN 实战视角)

维度 Zustand Redux Toolkit
学习成本 极低
样板代码 极少
Provider 不需要 必须
异步 原生支持 thunk / saga
DevTools
大型团队 一般 更适合

个人建议

  • RN 业务页面、模块级状态:Zustand
  • 复杂全局状态、多人协作:RTK
  • 二者可以共存

九、常见坑位总结

  1. 不要整 store 订阅
  2. 不要把所有状态塞进一个 store
  3. RN 中慎用大对象(列表分页要拆分)
  4. persist + AsyncStorage 要注意冷启动恢复时机

❌
❌