用zustand,简单理解

55 阅读2分钟

import { create } from 'zustand';

  


// 定义状态接口

interface CounterState {

count: number;

increment: () => void;

decrement: () => void;

reset: () => void;

}

  


// 创建zustand store

export const useCounterStore = create<CounterState>((set) => ({

count: 0,

increment: () => set((state) => ({ count: state.count + 1 })),

decrement: () => set((state) => ({ count: state.count - 1 })),

reset: () => set({ count: 0 }),

}));

  


// 用户信息状态

interface UserState {

user: {

name: string;

email: string;

} | null;

setUser: (user: { name: string; email: string }) => void;

clearUser: () => void;

}

  


export const useUserStore = create<UserState>((set) => ({

user: null,

setUser: (user) => set({ user }),

clearUser: () => set({ user: null }),

}));



import React from 'react';

import { useCounterStore } from '../store';

  


const Counter: React.FC = () => {

const { count, increment, decrement, reset } = useCounterStore();

  


return (

<div style={{

padding: '20px',

border: '1px solid #ccc',

borderRadius: '8px',

margin: '20px 0',

textAlign: 'center'

}}>

<h2>计数器示例</h2>

<div style={{ fontSize: '2rem', margin: '20px 0', color: '#61dafb' }}>

当前计数: {count}

</div>

<div style={{ display: 'flex', gap: '10px', justifyContent: 'center' }}>

<button

onClick={increment}

style={{

padding: '10px 20px',

fontSize: '16px',

backgroundColor: '#61dafb',

color: 'white',

border: 'none',

borderRadius: '4px',

cursor: 'pointer'

}}

>

增加

</button>

<button

onClick={decrement}

style={{

padding: '10px 20px',

fontSize: '16px',

backgroundColor: '#ff6b6b',

color: 'white',

border: 'none',

borderRadius: '4px',

cursor: 'pointer'

}}

>

减少

</button>

<button

onClick={reset}

style={{

padding: '10px 20px',

fontSize: '16px',

backgroundColor: '#feca57',

color: 'white',

border: 'none',

borderRadius: '4px',

cursor: 'pointer'

}}

>

重置

</button>

</div>

</div>

);

};

  


export default Counter;

加上immer 他就是在堆上生成新地址,Immer 的核心机制就是通过在堆上创建新的对象来实现不可变性。

传统方式 vs Immer

// 每层都要手动创建新对象

const newState = {

...state, // 新对象 1

user: {

...state.user, // 新对象 2

profile: {

...state.user.profile, // 新对象 3

name: 'New Name'

}

}

};

immer 方式 :

// Immer 自动处理对象创建

const newState = produce(state, draft => {

draft.user.profile.name = 'New Name';

// Immer 内部:

// 1. 检测到 draft.user 被访问 → 创建 user 的副本

// 2. 检测到 draft.user.profile 被访问 → 创建 profile 的副本

// 3. 检测到 draft.user.profile.name 被修改 → 标记为已修改

});

Immer 的优势

  1. 代码可读性 : 更接近直观的"修改"操作
  2. 减少错误 : 避免忘记展开操作符或深拷贝
  3. 性能优化 : Immer 只会更新实际改变的部分
  4. 类型安全 : 完全支持 TypeScript
  5. 调试友好 : 更容易理解状态变化

何时使用 Immer

  • ✅ 深层嵌套的对象结构
  • ✅ 复杂的数组操作
  • ✅ 多个字段同时更新
  • ✅ 团队协作(降低学习成本)
  • ❌ 简单的状态(如单个计数器)
  • ❌ 性能极度敏感的场景
  • ❌ 状态结构很扁平 总结 : Immer 让复杂状态管理变得像操作普通 JavaScript 对象一样简单,同时保持 React 状态管理的不可变性要求。

persist 是 Zustand 的一个中间件,主要作用就是将状态持久化存储到 localStorage (或其他存储方式)中。

import { persist } from 'zustand/middleware';

  


const useCounterStore = create(

persist(

(set) => ({

count: 0,

increment: () => set((state) => ({ count: state.count + 1 })),

}),

{

name: 'counter-storage', // localStorage 的 key 名称

}

)

);