使用 Zustand/Jotai 管理客户端状态
使用 Zustand 或 Jotai 实现轻量且高性能的客户端全局状态管理。
使用 Zustand/Jotai 管理客户端状态 是 CoddyKit 上的免费 Next.js 15 Fullstack Web Apps 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Next.js 15 Fullstack Web Apps 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Next.js 15 Fullstack Web Apps 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Global State: Beyond Local
In React, you've learned about local state with useState, which is great for data used only within a single component.
But what if data needs to be shared across many components, or deeply nested components, without 'prop drilling' (passing props down through many layers)? This is where client-side global state management comes in.
Global state allows any component to access or update shared data directly, simplifying complex data flows and making your application more maintainable.
Meet Zustand: Simple State
Zustand is a small, fast, and scalable state management solution for React. Its API is simple and hooks-based, making it very intuitive to learn and use.
- Minimalistic: Less boilerplate code.
- Fast: Optimized for performance.
- Flexible: Works with any React component.
- Hooks-based: Feels natural to React developers.
Get Started with Zustand
Before we dive into creating stores, you'll need to install Zustand in your Next.js project. It's a simple npm or yarn command.
Open your terminal in the project root and run:
npm install zustandOr if you prefer Yarn:
yarn add zustandOnce installed, you're ready to define your first store!
Crafting a Zustand Store
A Zustand store is created using the create function. This function takes a callback that defines your initial state and actions.
Think of a store as a central hub for specific pieces of global data. Let's create a basic counter store:
import { create } from 'zustand';
// Define your store
const useCounterStore = create((set) => ({
count: 0,
}));
// This store can be imported and used in your React components.
// It's not runnable on its own, but defines the global state structure.Store State & Actions
Beyond just holding state, a store also contains actions – functions that modify the state. The set function provided by Zustand allows you to update the store's state.
Here's how we add increment and decrement actions to our counter store:
import { create } from 'zustand';
const useCounterStore = create((set) => ({
count: 0,
// Action to increment count
increment: () => set((state) => ({ count: state.count + 1 })),
// Action to decrement count
decrement: () => set((state) => ({ count: state.count - 1 })),
}));
// This store now has both state (count) and actions (increment, decrement).Connect Components to Store
To use the global state in your React components, you simply import the store hook (e.g., useCounterStore) and call it. You can select specific pieces of state or actions.
Let's create a component that displays the current count from our store:
import { create } from 'zustand';
// Define your store (as in previous scenes)
const useCounterStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}));
// A React component that uses the store
export default function CounterDisplay() {
// Select the 'count' state from the store
const count = useCounterStore((state) => state.count);
return (
<div>
<p>Current Count: {count}</p>
</div>
);
}
// This component can be rendered in a Next.js page or another component.Interactive Counter Example
Now let's make our counter interactive! We'll add buttons that call the increment and decrement actions defined in our store.
This shows how components can both read from and write to the global state, keeping everything synchronized.
import { create } from 'zustand';
// Define your store
const useCounterStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}));
// A React component that uses the store and its actions
export default function InteractiveCounter() {
// Select both state and actions
const { count, increment, decrement } = useCounterStore();
return (
<div>
<p>Count: {count}</p>
<button onClick={decrement}>Decrement</button>
<button onClick={increment}>Increment</button>
</div>
);
}
// This component is fully runnable and demonstrates Zustand in action.Efficient State Selection
By default, if any part of the store's state changes, components that use the store might re-render. To optimize this, you can use selectors.
A selector is a function you pass to useStore that picks only the specific data your component needs. If only that selected data changes, the component re-renders.
import { create } from 'zustand';
// A more complex store with multiple states
const useSettingsStore = create((set) => ({
theme: 'dark',
fontSize: 16,
toggleTheme: () => set((state) => ({ theme: state.theme === 'dark' ? 'light' : 'dark' })),
setFontSize: (size) => set({ fontSize: size }),
}));
// Component only cares about 'theme'
export default function ThemeDisplay() {
// Using a selector to only subscribe to 'theme'
const theme = useSettingsStore((state) => state.theme);
return (
<p>Current Theme: <b>{theme}</b></p>
);
}
// If fontSize changes, ThemeDisplay will NOT re-render because it only selects 'theme'.Zustand Best Practices
To keep your Zustand stores clean and efficient:
- Immutability: Always update state immutably. Don't directly modify objects or arrays in state; create new ones.
- Separate Concerns: Keep related state and actions in the same store. Create multiple stores for different domains (e.g.,
useUserStore,useCartStore). - Selectors: Use selectors to prevent unnecessary re-renders in components.
- Middleware: For advanced features like persistence or logging, explore Zustand's middleware options.
Zustand Knowledge Check
Zustand offers a flexible and lightweight approach to global state management. Based on what you've learned, choose the correct statements about its benefits and characteristics.
Zustand: A Quick Recap
Congratulations! You've learned the fundamentals of client-side global state management with Zustand.
- We explored why global state is essential for complex apps.
- You saw how to define a Zustand store with state and actions using
create. - We learned to connect React components to the store and interact with its state and actions.
- Finally, we discussed how selectors can optimize component re-renders.
Zustand empowers you to manage shared data efficiently, making your Next.js applications more scalable and easier to maintain.
常见问题解答
「使用 Zustand/Jotai 管理客户端状态」课时是免费的吗?
是的 — 「使用 Zustand/Jotai 管理客户端状态」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Next.js 15 Fullstack Web Apps 课程的其余内容,请升级到 CoddyKit PRO。 Next.js 15 Fullstack Web Apps 课程共包含 4 节课。
「使用 Zustand/Jotai 管理客户端状态」这节课中我会学到什么?
使用 Zustand 或 Jotai 实现轻量且高性能的客户端全局状态管理。 你通过在浏览器中直接运行的动手代码来练习 Next.js 15 Fullstack Web Apps,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Next.js 15 Fullstack Web Apps 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Next.js 15 Fullstack Web Apps 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「使用 Zustand/Jotai 管理客户端状态」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Next.js 15 Fullstack Web Apps 课中编写并运行代码吗?
能。每节 Next.js 15 Fullstack Web Apps 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 React Query 管理服务器状态
- 使用 Zustand/Jotai 管理客户端状态
- 服务器端缓存策略
- 乐观更新与缓存失效