切片模式与 Devtools 集成
使用切片模式将大型存储组织为逻辑切片,并添加 Zustand DevTools 中间件,以便在开发过程中进行时间旅行调试。
切片模式与 Devtools 集成 是 CoddyKit 上的免费 React Native Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Native Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Native Academy 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Why Organize Stores with Slices?
As a Zustand store grows, keeping all state and actions in a single object becomes hard to maintain. The slices pattern splits the store into multiple focused sections, each defined as a separate function. All slices are combined into one store, so components still access everything through a single hook. This mirrors the Redux Toolkit slice concept but in Zustand's minimal style.
Defining a Slice Function
A Zustand slice is a function that accepts set, get, and optionally the whole store initializer, and returns an object containing state and actions for that domain. Define each slice in its own file and import them into the combined store. The slice function signature mirrors the main store creator exactly.
// slices/counterSlice.ts
import type { StateCreator } from 'zustand';
import type { AppStore } from '../useAppStore';
export interface CounterSlice {
count: number;
increment: () => void;
decrement: () => void;
reset: () => void;
}
export const createCounterSlice: StateCreator<AppStore, [], [], CounterSlice> =
(set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
reset: () => set({ count: 0 }),
});Combining Slices into One Store
Import all your slice creator functions and merge them inside a single create call using the spread operator. The combined store type is the intersection of all slice interfaces. Components can then access any slice's state and actions through the same useAppStore hook.
// useAppStore.ts
import { create } from 'zustand';
import { createCounterSlice, CounterSlice } from './slices/counterSlice';
import { createUserSlice, UserSlice } from './slices/userSlice';
export type AppStore = CounterSlice & UserSlice;
export const useAppStore = create<AppStore>((set, get, api) => ({
...createCounterSlice(set, get, api),
...createUserSlice(set, get, api),
}));Cross-Slice Communication
Slices can call each other's actions or read each other's state using the get function. This is how one slice can react to another slice's changes without tight coupling. For example, a cart slice can read the user slice's auth token and include it in an API request when checking out.
export const createCartSlice: StateCreator<AppStore, [], [], CartSlice> =
(set, get) => ({
items: [],
checkout: async () => {
const token = get().user.token; // read from userSlice
await api.checkout(get().items, token);
set({ items: [] });
},
});What Is the Zustand DevTools Middleware?
The devtools middleware connects your Zustand store to the Redux DevTools browser extension. Once connected, you can inspect every state snapshot, view the action name that triggered each change, and time-travel back to any previous state. It is invaluable for debugging complex state sequences during development.
Adding DevTools Middleware
Wrap your store creator with the devtools middleware imported from zustand/middleware. Pass an optional configuration object with a name property to label the store in the DevTools panel. Only enable DevTools in development to avoid performance overhead in production builds.
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
export const useCounterStore = create(
devtools(
(set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
reset: () => set({ count: 0 }),
}),
{ name: 'CounterStore' }
)
);Labeling Actions in DevTools
By default, DevTools labels every state change with anonymous. Pass a descriptive string as the third argument to set to give each action a meaningful name in the DevTools timeline. This makes it much easier to trace which user interaction triggered each state change.
increment: () =>
set(
(state) => ({ count: state.count + 1 }),
false, // false = merge (not replace)
'counter/increment' // action label in DevTools
),
reset: () =>
set({ count: 0 }, false, 'counter/reset'),Combining DevTools with persist
When using both persist and devtools, wrap the store in both middlewares. The order matters: devtools should be the outermost wrapper so it can observe all state changes, including those from rehydration. Nest persist inside devtools to see rehydration actions in the DevTools timeline.
import { create } from 'zustand';
import { persist, devtools, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';
export const useSettingsStore = create(
devtools(
persist(
(set) => ({ theme: 'light', setTheme: (t) => set({ theme: t }) }),
{ name: 'settings', storage: createJSONStorage(() => AsyncStorage) }
),
{ name: 'SettingsStore' }
)
);Slices with persist and DevTools
In large apps, combine all three patterns: slices for organization, persist for storage, and devtools for debugging. Wrap the merged slice object with persist and devtools. Define the combined type as the intersection of all slice interfaces so TypeScript correctly types the full store.
export const useAppStore = create<AppStore>()(
devtools(
persist(
(set, get, api) => ({
...createCounterSlice(set, get, api),
...createUserSlice(set, get, api),
}),
{ name: 'app-store', storage: createJSONStorage(() => AsyncStorage) }
),
{ name: 'AppStore' }
)
);Naming Conventions for Slices
Use consistent naming to make large stores easy to navigate. Name slice files after the domain (e.g., authSlice.ts, cartSlice.ts), prefix action names with the domain in DevTools labels (e.g., auth/login, cart/addItem), and keep each slice under 100 lines. Split further if a slice starts handling unrelated concerns.
When Not to Use Slices
The slices pattern adds complexity. If your store has fewer than five state fields and two or three actions, keep it as a single create call — the overhead of splitting is not worth it. Reserve slices for stores that have grown to the point where a single file is difficult to understand or when multiple developers work on different features that share the same store.
Quick Check
Test your understanding of React Native Mobile Development concepts from this lesson.
Lesson Recap
In this lesson you learned: the slices pattern splits a large Zustand store into focused domain functions that are merged in one create call, the devtools middleware connects the store to Redux DevTools for state inspection and time-travel, and labeling set calls with action name strings makes the DevTools timeline meaningful. Next up we explore reading and writing with AsyncStorage directly.
用 AI 导师学习 JavaScript — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 30
- 课程
- 120
常见问题解答
「切片模式与 Devtools 集成」课时是免费的吗?
是的 — 「切片模式与 Devtools 集成」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Native Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Native Academy 课程共包含 4 节课。
「切片模式与 Devtools 集成」这节课中我会学到什么?
使用切片模式将大型存储组织为逻辑切片,并添加 Zustand DevTools 中间件,以便在开发过程中进行时间旅行调试。 你通过在浏览器中直接运行的动手代码来练习 React Native Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Native Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Native Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。
「切片模式与 Devtools 集成」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Native Academy 课中编写并运行代码吗?
能。每节 React Native Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 创建 Zustand 存储
- 在组件中读取和更新存储状态
- 使用 AsyncStorage 持久化 Zustand 状态
- 切片模式与 Devtools 集成