Skip to content

Redux

介绍

Redux 是一个 JavaScript 状态容器,提供可预测化的状态管理。

快速入门

安装

bash
npm i @reduxjs/toolkit@1 react-redux@8
  • @reduxjs/toolkit:内置了很多了工具包,简化 Redux 的使用方式。
  • react-redux:用于链接 React 和 Redux。

示例

项目结构

bash
src
└─ store
   ├─ modules
  ├─ counter.js
  ├─ user.js
  └─ ...
   └─ index.js

定义

ts
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { Provider } from 'react-redux'
import store from './store'

import App from './App.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </StrictMode>,
)
ts
import { configureStore } from '@reduxjs/toolkit'
import counter from './modules/counter'

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

export type RootState = ReturnType<typeof store.getState>
export type RootDispatch = typeof store.dispatch

export default store
ts
import { createSlice } from '@reduxjs/toolkit'
import type { RootDispatch } from '../index'

const counterStore = createSlice({
  name: 'counter',
  // 初始化 state
  initialState: {
    count: 0,
  },
  // 同步操作,直接修改
  reducers: {
    increment(state, action) {
      state.count += action.payload
    },
    decrement(state, action) {
      state.count -= action.payload
    },
  },
})

// 解构出 actionCreator
const { increment, decrement } = counterStore.actions

// 异步操作,返回一个函数
const asyncIncrement = (val: number) => {
  return async (dispatch: RootDispatch) => {
    setTimeout(() => {
      dispatch(increment(val * 100))
    }, 3000)
  }
}

// 获取 reducer
const reducer = counterStore.reducer

export { increment, decrement, asyncIncrement }
export default reducer

使用

tsx
import { useSelector, useDispatch } from 'react-redux'
import type { RootState, RootDispatch } from '../../store'
import { increment, decrement, asyncIncrement } from '../../store/modules/counter'

function ReduxView() {
  // 获取 state 中的数据
  const { count } = useSelector((state: RootState) => state.counter)
  // 获取 dispatch 方法
  const dispatch = useDispatch<RootDispatch>()

  return (
    <>
      {/* 调用 dispatch 方法  */}
      <button onClick={() => dispatch(increment(2))}>+2</button>
      {/* 异步 dispatch  */}
      <button onClick={() => dispatch(asyncIncrement(2))}>异步 ++</button>
      <span>{count}</span>
      <button onClick={() => dispatch(decrement(1))}>-1</button>
    </>
  )
}

export default ReduxView

Redux 的核心思想

为什么需要 Redux?

在构建复杂的前端应用时,常常会遇到这些问题:

  1. 状态分散:应用的状态(state)分散在各个独立的组件中,难以形成全局视图。
  2. 数据流混乱:组件层级加深,数据通过 Props 层层传递,或者通过事件随意通信,导致数据流难以追踪和维护。
  3. 变更不可预测:一个状态可能在任意组件、任意时刻被修改,当出现 bug 时,很难定位是哪个环节导致了错误的状态。

于是 Redux 便诞生了,Redux 并非一个复杂的框架,而是一套状态管理模式,它让状态的变化变得可预测、可追溯。

Redux 的三大原则

  1. 单一数据源:整个应用的 state 都被存储在一个 store 中的一棵对象树中。
  2. 状态只读:状态不能直接修改,唯一改变 state 的方法就是触发 action,一个描述发生了什么的对象。
  3. 变更由纯函数完成:为了描述 action 如何改变 state 树,需要编写 reducers

什么是 action?

action 本质就是一个普通的 js 对象:

  1. 必须包含一个 type 字段(通常是字符串),用来描述发生了什么。
  2. 可以携带一些更新数据所需要的消息,这部分通常被成为 payload。
js
const addTodoAction = {
  type: 'ADD_TODO',
  payload: {
    text: 'Learn Redux',
  },
}

Zustand 核心特点

  1. 极简的 API 和模板代码:没有 actions、reducers、dispatch 等概念,所有逻辑都封装在 create 函数中,上手极快。
  2. 无需 Provider:状态是全局的,不依赖于 React Context。无需在根组件通过 <Provider> 包裹组件,可随时地调用。
  3. 基于 Selector 的性能优化:组件通过 selector 函数订阅状态的一部分。只有被订阅的状态变化时,组件才会被重新渲染,天然避免了不必要的渲染。
  4. 灵活性高:支持集成中间件,可轻松集成 Redux DevTools、日志、持久化存储等功能。

基于 MIT 许可发布