# 核心概念：State 与 Actions

URL: https://caijiao.org/zustand/guide/core-concepts
Source: docs/zustand/guide/core-concepts.md
Description: 深入理解 Zustand 的核心概念，包括 State（应用数据源）、Actions（修改状态的方法）和 Store（状态与动作的集合），以及不可变更新、计算属性等高级特性。

在 [Zustand](../) 中，状态管理的核心是 Store（存储），它包含了应用的 State（状态）和 Actions（动作）。理解这些核心概念是掌握 Zustand 的关键。

## State：应用的数据源

State 是应用的数据容器，它存储了应用的所有状态信息。在 Zustand 中，State 可以是任何 JavaScript 类型，包括对象、数组、字符串、数字等。

```javascript
// 简单的状态
const useStore = create(() => ({
  count: 0,
  name: 'Zustand',
  isLoading: false,
  items: [],
}))
```

## Actions：修改状态的方法

Actions 是修改 State 的函数。在 Zustand 中，Actions 直接定义在 Store 内部，与 State 共存。

```javascript
const useStore = create((set) => ({
  // State
  count: 0,
  
  // Actions
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
  setName: (name) => set({ name }),
  setLoading: (isLoading) => set({ isLoading }),
}))
```

## Store：状态与动作的集合

Store 是 Zustand 的核心，它将 State 和 Actions 组织在一起。创建 Store 使用 `create` 函数，它接受一个函数作为参数，该函数返回 Store 的初始状态和动作。

### Store 创建函数的参数

Store 创建函数接收两个参数：

1. **set**：用于修改状态的函数
2. **get**：用于获取当前状态的函数

```javascript
const useStore = create((set, get) => ({
  count: 0,
  
  increment: () => set((state) => ({ count: state.count + 1 })),
  
  // 使用 get 获取当前状态
  incrementTwice: () => {
    const currentCount = get().count
    set({ count: currentCount + 2 })
  },
}))
```

## 不可变更新

Zustand 鼓励使用不可变更新模式，这意味着你不应该直接修改状态对象，而是应该创建一个新的状态对象。

### 错误的做法

```javascript
// 不要这样做！
const useStore = create((set) => ({
  user: { name: 'John', age: 30 },
  
  updateAge: (age) => {
    set((state) => {
      state.user.age = age // 直接修改状态对象
      return state
    })
  },
}))
```

### 正确的做法

```javascript
// 这样做是正确的
const useStore = create((set) => ({
  user: { name: 'John', age: 30 },
  
  updateAge: (age) => {
    set((state) => ({
      user: {
        ...state.user, // 复制现有属性
        age, // 更新年龄
      },
    }))
  },
}))
```

## 在组件中使用 State 和 Actions

在 React 组件中，你可以使用自定义 Hook 来访问 Store 中的 State 和 Actions。

### 访问单个状态

```jsx
const count = useStore((state) => state.count)
```

### 访问多个状态

```jsx
const { count, name } = useStore((state) => ({ 
  count: state.count, 
  name: state.name 
}))
```

### 访问 Actions

```jsx
const increment = useStore((state) => state.increment)
const { increment, decrement } = useStore((state) => ({ 
  increment: state.increment, 
  decrement: state.decrement 
}))
```

### 完整示例

```jsx
function Counter() {
  const count = useStore((state) => state.count)
  const { increment, decrement, reset } = useStore((state) => ({
    increment: state.increment,
    decrement: state.decrement,
    reset: state.reset,
  }))

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={reset}>Reset</button>
    </div>
  )
}
```

## 高级状态管理

### 计算属性

你可以在 Store 中定义计算属性，它们基于其他状态计算得出。

```javascript
const useStore = create((set, get) => ({
  todos: [
    { id: 1, text: 'Learn Zustand', completed: true },
    { id: 2, text: 'Build an app', completed: false },
  ],
  
  // 计算属性：完成的任务数量
  completedTodosCount: () => get().todos.filter((todo) => todo.completed).length,
  
  // 计算属性：待完成的任务数量
  pendingTodosCount: () => get().todos.filter((todo) => !todo.completed).length,
}))
```

### 在组件中使用计算属性

```jsx
function TodoStats() {
  const completedCount = useStore((state) => state.completedTodosCount())
  const pendingCount = useStore((state) => state.pendingTodosCount())

  return (
    <div>
      <p>Completed: {completedCount}</p>
      <p>Pending: {pendingCount}</p>
    </div>
  )
}
```

## State 与 Actions 的最佳实践

### 1. 将相关的状态和动作组织在一起

```javascript
// 好的做法：将计数器相关的状态和动作组织在一起
const useCounterStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
  decrement: () => set((state) => ({ count: state.count - 1 })),
}))
```

### 2. 保持 Actions 简洁

```javascript
// 好的做法：每个 Action 只做一件事
const useUserStore = create((set) => ({
  user: null,
  isLoading: false,
  error: null,
  
  fetchUser: async (id) => {
    set({ isLoading: true, error: null })
    try {
      const response = await fetch(`/api/users/${id}`)
      const user = await response.json()
      set({ user, isLoading: false })
    } catch (error) {
      set({ error: error.message, isLoading: false })
    }
  },
}))
```

### 3. 使用选择器避免不必要的重渲染

```jsx
// 好的做法：只订阅需要的状态
const count = useStore((state) => state.count)

// 不好的做法：订阅整个 Store
const store = useStore()
const count = store.count
```

## 总结

State 和 Actions 是 Zustand 的核心概念：

- **State** 是应用的数据源，存储了应用的所有状态信息
- **Actions** 是修改 State 的函数，定义在 Store 内部
- **Store** 将 State 和 Actions 组织在一起，是 Zustand 的核心
- 使用不可变更新模式修改状态
- 使用选择器精确订阅状态，避免不必要的重渲染

理解这些核心概念后，你就可以开始构建更复杂的状态管理逻辑了。在接下来的章节中，我们将学习 [性能优化：Selector 与 Shallow](performance-optimization.md)，进一步提升你的 Zustand 应用性能。
