1️⃣ zustand 的基本使用方法
在 zustand 中,你通常会这样创建一个 store:
1 2 3 4 5 6 |
import { create } from 'zustand'; const useUserStore = create((set) => ({ user: null, setUser: (user) => set({ user }), })); |
然后在组件中使用时,是这样的:
1 2 3 4 5 6 7 |
function MyComponent() { const user = useUserStore((state) => state.user); const setUser = useUserStore((state) => state.setUser); // 调用 setUser 更新状态 return <button onClick={() => setUser({ name: '张三' })}>更新用户</button>; } |
✅ 为什么要用回调函数 useUserStore((state) => state.xxx)?
- 因为 zustand 设计了一个订阅机制,它只会订阅你指定的 state 片段。
- 如果你直接调用 const store = useUserStore(),那实际上会返回整个 store,但 不带订阅功能,也就是说 不会自动更新组件。
- zustand 的 hook 形式是为了配合 React 的状态系统,自动触发组件的更新。
2️⃣ 为什么不能直接这样用?
1 2 3 |
// 你可能想这么写 const userStore = useUserStore(); // 然后 userStore.setUser() |
可以写,但有问题:
- 这种写法相当于取整个 store 对象,没有自动更新能力。
- 组件不会根据 user 的变化自动重新渲染。
- 因为 useUserStore() 返回的是 当前值的快照,而不是响应式引用(不像 Vue 里的 ref)。
✅ 正确写法应该是:
1 2 |
const user = useUserStore((state) => state.user); // 订阅 user const setUser = useUserStore((state) => state.setUser); // 获取 setUser |
这样 user 变了,组件会重新渲染。
3️⃣ 什么时候可以用 const store = useUserStore()?
- 在非组件逻辑中(比如自定义 hook 或 utils),你可以直接调用 useUserStore.getState() 或 useUserStore()。
- 比如:
1 2 3 4 5 |
// 某个 utils.js import { useUserStore } from './store'; const store = useUserStore.getState(); store.setUser({ name: '张三' }); // OK |
- 但在组件中,你需要让组件订阅状态变化,因此需要使用 useUserStore((state) => state.xxx)。
4️⃣ 总结
使用方式 | 是否自动订阅 | 是否推荐 |
---|---|---|
const state = useUserStore() | ❌ 否 | 🚫 不推荐(除非不需要订阅) |
const data = useUserStore((state) => state.xxx) | ✅ 是 | ✅ 推荐 |
useUserStore.getState() | ❌ 否 | ✅ 可在非组件逻辑中使用 |