React-状态管理器:zustand vs react-redux

Jiafeng

分类: React 23 0

组件通信的四大分类

1. 父子组件通信(props + callback)

> 父组件直接在子组件标签上写属性,子组件通过使用props接收数据

🌱 父组件向子组件传数据

function Parent() {
  const [message, setMessage] = useState("Hello from Parent")

  return (
    <div>
      <Child message={message} /> // 
    </div>
  )
}

// 子组件
function Child({ message }) {
  return <p>{message}</p>
}

🔄 子组件向父组件传数据

> 父组件在子组件标签上绑定函数,子组件调用函数并将变量作为参数传入该函数

```jsx
function Parent() {
const handleChildMessage = (childMsg) => {
alert(`收到子组件的消息:${childMsg}`)
}

return (
<div>
<Child onSendMessage={handleChildMessage} />
</div>
)
}

// 子组件
function Child({ onSendMessage }) {
return (
<button onClick={() => onSendMessage("来自子组件!")}>
发送消息
</button>
)
}


 ### 2. **兄弟组件通信(父组件作为中转站)**

 > 兄弟组件之间通信的关键点在于在父组件共享状态,可以**先子传父组件,再父传子组件**

 ```jsx
  const [sharedData, setSharedData] = useState("初始数据") // 父组件中设置共享的状态

  return (
    <div>
      <ChildA onSendData={setSharedData} />
      <ChildB sharedData={sharedData} />
    </div>
  )
}

// 兄弟A发送数据
function ChildA({ onSendData }) {
  return (
    <input
      onChange={(e) => onSendData(e.target.value)}
      placeholder="输入数据"
    />
  )
}

// 兄弟B接收数据
function ChildB({ sharedData }) {
  return <p>共享数据:{sharedData}</p>
}

3. 跨层级通信(Context API)

> 设组件A是组件B的父组件,组件B是组件C的父组件

要将A中的变量传递给C组件,需要创建全局`Context`组件

  1. 组件A中使用Context.Provider包裹组件B

    1. 在C组件中使用`useContext`获取Context组件中的变量

    ```jsx

const myContext = createContext() // 创建全局的Context进行数据的传递

function B () { // 孙子组件
const msg = useContext(myContext) // 获取父组件传递的值
return (
<div>
<h3>Component B --{msg}</h3>
</div>
)
}

function A () { // 子组件
const msg = useContext(myContext) // 获取父组件传递的值
return (
<div>
<h1>Component A --{msg}</h1>
<B/>
</div>
)
}

function Index () { // 父组件
const [msg, setMsg] = useState('Hello from Grandparents')
return (
<div>
<myContext.Provider value={msg}>
<A/>
</myContext.Provider>
</div>
)
}


 ### 4. **任意组件通信(全局仓库)**

 在面对完全没有父子或者层级关系的组件之间进行通信的情况时,上述的三种方法就会显得鸡肋和乏力。如果硬要用这种方法写代码会极其冗杂,难以维护。这个时候就需要全局仓库了。各个组件即用即取,仓库对状态进行统一管理。不需要多余的代码和心智负担。

 #### 全局仓库的优势

 1. **解决跨组件通信复杂性**

   - 在大型应用中,组件层级深、关系复杂时,直接通过 props 传递状态(Prop Drilling)会导致代码臃肿、难以维护。
  - **全局仓库**提供统一的状态访问入口,避免逐层传递状态或回调函数。
1. **集中管理共享状态**

   - 所有组件都可以直接从全局仓库读取或更新状态,避免状态分散在多个组件中,降低耦合度。
1. **支持复杂业务逻辑**

   - 全局仓库可以处理异步操作(如 API 请求)、中间件逻辑(如日志记录、权限控制)等,适合需要复杂状态管理的场景。
1. **提高可维护性和可测试性**

   - 全局状态的变更集中管理,便于调试和单元测试,代码结构更清晰。
1. **统一状态源**

   - 所有组件共享一个真实的状态源,避免数据不一致(如多个组件修改同一状态导致冲突)。

 > 全局的状态管理仓库目前有非常多,不论是官方打造的Redux还是第三方封装的仓库例如Zustandmobxvaltio。
 ---

 ## 🧩 Zustand 和 Redux 仓库详解 -- 以计数器为例

 ### 一、Redux仓库

 1. @reduxjs/toolkit (创建子模块仓库)
1. 创建一个总仓库,在总仓库中注册各个子模块,子模块通常在modules目录下
1. react-redux(在根组件中连接仓库和react)
1. 在组件中使用useSelector获取仓库中的数据
1. 在组件中使用useDispatch获取仓库中的函数
1. 调用仓库中的方法 得到一个action行为
1. 调用dispatch函数将action行为派发给仓库

 ---

 > Redux使用时目录结构示例

 ```bash
src/
├── modules/
│   └── counterSlice.js        # 子模块
├── store.js                   # 总仓库
├── App.jsx                    # 根组件
└── Counter.jsx                # 使用状态的组件

Redux 的经典流程

🛠️ 1. 创建 Slice--创建子模块

```jsx
import { createSlice } from '@reduxjs/toolkit'

const counterSlice = createSlice({
name: 'counter',
initialState: { count: 0 },
reducers: {
increment(state) {
state.count += 1
},
decrement(state) {
state.count -= 1
}
}
})

export const { increment, decrement } = counterSlice.actions
export default counterSlice.reducer


 ##### 🧱 2. 配置 Store

 ```jsx
import { configureStore } from '@reduxjs/toolkit'
import counterReducer from './counterSlice'

const store = configureStore({
  reducer: {
    counter: counterReducer
  }
})

export default store
🔗 3. 在根组件中连接仓库--使仓库全局可用(`App.jsx`)

```jsx
import { Provider } from 'react-redux';
import store from './store';
import Counter from './Counter';

const App = () => (
<Provider store={store}>
{/ 使用Provider包裹App组件,传入store /}
<Counter />
</Provider>
);

export default App;


 ##### 🧩 4. 组件中使用仓库

 ```jsx
// 步骤 2:连接仓库和react
import { useSelector, useDispatch } from 'react-redux'
import { increment, decrement } from './counterSlice'

function Counter() {

  // 步骤 4:使用 useSelector 获取状态
  const count = useSelector(state => state.counter.count)

  // 步骤 5:使用 useDispatch 获取 dispatch 函数
  const dispatch = useDispatch()

  // 步骤 6-7:调用 action 并 dispatch
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => dispatch(increment())}>+1</button>
      <button onClick={() => dispatch(decrement())}>-1</button>
    </div>
  )
}

二、Zustand 仓库

  1. `zustand`(创建状态仓库)

    1. 不需要额外库(Zustand 天然支持 React,无需像 `react-redux`)
    2. 创建一个总仓库,在总仓库中可以组合多个子模块或功能,通常将子模块放在 `stores` 或 `modules` 目录下
    3. 在组件中使用 `useStore` 获取仓库中的数据
    4. 在组件中直接调用 `useStore` 返回的 `actions`(或方法)来修改状态
    5. 调用仓库中的方法,直接修改状态(Zustand 中不需要 `action` 和 `dispatch`
    6. Zustand 中状态修改是直接的,不需要 `dispatch`,调用方法即刻更新状态

    > Zustand 项目目录结构示例

    ```bash
    ├── stores/ # 所有 Zustand 仓库存放的目录
    │ └── counterStore.js # 示例:计数器模块
    ├── App.jsx # 根组件
    └── Counter.jsx # 使用状态的组件

    
    
    #### **Zustand 的使用流程**
    
    #### 1. 创建状态仓库(核心步骤)
    
    ```jsx
    import create from 'zustand'

export default const counterStore = create(set => ({
// 🎯 初始状态
count: 0,
// 🛠️ 修改状态的方法
increment: () => set(state => ({ count: state.count + 1 })),
decrement: () => set(state => ({ count: state.count - 1 }))
}))


 📌 **步骤拆解**:

 1. `create()` 是 Zustand 的魔法工厂
1. `set` 是状态修改的钥匙🔑
1. 返回对象包含:   - ✅ 初始状态(`count`)
  - ✅ 修改方法(`increment`, `decrement`)

 ---

 #### 2. 组件中使用状态(实战演示)

 ```jsx
// Counter.jsx
import { useCounterStore } from '../stores/counterStore.js'

function Counter() {
  // 🧾 获取状态和方法
  const { count, increment, decrement } = useCounterStore()

  return (
    <div>
      <p>{count}</p>
      <button onClick={increment}>+1</button>
      <button onClick={decrement}>-1</button>
    </div>
  )
}

💡 小贴士

  • useCounterStore() 直接返回整个 store 的状态和方法

    • 所有组件调用同一个 store 都会自动同步更新✨

    🧪 Zustand 与 Redux 对比(重点篇)

    1. Zustand 的核心优势

    超轻量 API
  • 创建 storecreate(set => ({ ... }))

    • 使用 storeconst useStore = create(...) 直接返回 hook
    • 无中间层:不需要 Providerconnect,直接调用 hook

    3. Zustand vs Redux 对比表

    特性 Zustand Redux Toolkit
    学习成本 🟢 更简单,适合新手 🔵 需要理解中间件、action、reducer 等概念
    API 设计 ✨ 直接使用 hook,无需 Provider 🧩 需要 Provider 和 connect
    模块化 🧩 自动模块化,每个 store 独立 🧱 需要手动拆分多个 slice
    异步操作 🚀 可直接在 action 中写 async/await ⚙️ 需要配合 createAsyncThunk
    性能优化 🚀 自动订阅,无需 createSelector ⚙️ 需要 createSelector 优化选择器
    适合场景 🚀 小型项目、快速原型开发 🧱 大型复杂应用

    🧠 总结:选择最适合的方案

  • 小型项目:优先使用 Zustand,代码简洁,上手快

    • 中型项目:Zustand + Context API 可以替代 Redux
    • 大型项目:Redux Toolkit 提供更完善的工具链
    • 跨组件通信:Zustand 的 hook 设计天然支持全局状态共享
  • 0人 Love
  • 0人 Haha
  • 0人 Wow
  • 0人 Sad
  • 0人 Angry
React

作者简介: Jiafeng

共 0 条评论关于 “React-状态管理器:zustand vs react-redux”

Loading...