一、Zustand 是什么,适合什么场景
Zustand 是一个轻量级、基于 hooks 的状态管理库,核心特点是:
- 无 Provider(无需 Context 包裹)
- API 极简(create + hooks)
- 按需订阅(避免无关组件重渲染)
- 对 React Native 友好(无额外平台依赖)
- 可渐进式引入
非常适合以下 RN 场景:
- 中小规模应用
- RN Hybrid / Module 化工程
- UI 状态 + 业务状态混合管理
- 替代部分 Redux 的场景
二、安装
bash
yarn add zustand
# 或
npm install zustand
React Native 无需额外配置。
三、最基础用法(核心必会)
1. 创建 Store
ts
// 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. 在组件中使用
tsx
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) - 只订阅使用到的字段,避免全量刷新
四、推荐的工程化写法(重要)
❌ 不推荐
ts
const store = useStore();
这样会导致任意状态变更都触发重渲染
✅ 推荐:拆分 selector
ts
const count = useCounterStore((s) => s.count);
const inc = useCounterStore((s) => s.inc);
或:
ts
const { count, inc } = useCounterStore(
(s) => ({ count: s.count, inc: s.inc })
);
五、Zustand 在 React Native 中的常见模式
1. 全局 UI 状态(Loading / Modal)
ts
type UIState = {
loading: boolean;
showLoading: () => void;
hideLoading: () => void;
};
export const useUIStore = create<UIState>((set) => ({
loading: false,
showLoading: () => set({ loading: true }),
hideLoading: () => set({ loading: false }),
}));
tsx
const loading = useUIStore((s) => s.loading);
2. 业务状态(登录信息)
ts
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(非常自然)
ts
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 避免对象对比
ts
import { shallow } from 'zustand/shallow';
const { count, inc } = useCounterStore(
(s) => ({ count: s.count, inc: s.inc }),
shallow
);
2. 将高频 UI 状态拆分 Store
text
store/
├── useAuthStore.ts
├── useUIStore.ts
├── useListStore.ts
避免一个大 Store。
七、持久化(AsyncStorage)
RN 常用:zustand + persist
ts
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
- 二者可以共存
九、常见坑位总结
- 不要整 store 订阅
- 不要把所有状态塞进一个 store
- RN 中慎用大对象(列表分页要拆分)
- persist + AsyncStorage 要注意冷启动恢复时机
