Skip to content

一、先给你一个学习全景图

Redux 的演进脉络(很重要)

  1. Redux(经典)

    • createStore
    • reducer / action
    • middleware(thunk、logger)
  2. React-Redux

    • <Provider />
    • connect
  3. Hooks 时代

    • useSelector
    • useDispatch
  4. Redux Toolkit(RTK,官方推荐)

    • configureStore
    • createSlice
    • createAsyncThunk
    • 内置 immer + thunk
  5. RTK Query(服务端状态)

    • 请求 / 缓存 / 去重 / 失效

👉 现在 90% 的 Redux 项目 = Redux Toolkit + Hooks

二、Redux 解决的“本质问题”

Redux = 可预测的全局状态管理 + 显式的状态变更轨迹

Redux 解决什么?

  • 跨组件 / 跨层级共享状态
  • 状态变化可追踪(时间旅行、日志)
  • 状态变化逻辑 从组件中抽离

Redux 不适合什么?

  • 表单局部状态
  • UI 临时状态(hover / open)
  • 高频瞬时状态(mousemove)

三、Redux 核心思想(先不用写代码)

1️⃣ 单一数据源(Single Store)

txt
UI → dispatch(action) → reducer → new state → UI

2️⃣ 状态是只读的

  • 不能 store.state.xxx = 1
  • 只能通过 dispatch

3️⃣ 使用纯函数更新状态

js
(state, action) => newState

这三条 = Redux 的“宪法”

四、现代 Redux(RTK)最小心智模型

Redux Toolkit 帮你做了什么?

  • 自动组合 reducer
  • 自动接入 thunk
  • 自动接入 immer(你可以“写可变代码”)
  • 开箱即用 DevTools

你真正要理解的只有 4 个东西

txt
Store
Slice
Dispatch
Selector

五、从 0 到 1 的最小 RTK 示例(精华)

1️⃣ 创建 slice(状态 + reducer + action)

js
import { createSlice } from '@reduxjs/toolkit'

const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment(state) {
      state.value++
    },
    addBy(state, action) {
      state.value += action.payload
    }
  }
})

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

⚠️ 这里能“直接改 state”是因为 immer

2️⃣ 创建 store

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

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

3️⃣ 注入 React

js
import { Provider } from 'react-redux'
import { store } from './store'

root.render(
  <Provider store={store}>
    <App />
  </Provider>
)

4️⃣ 在组件里用

js
import { useSelector, useDispatch } from 'react-redux'
import { increment } from './counterSlice'

function Counter() {
  const value = useSelector(state => state.counter.value)
  const dispatch = useDispatch()

  return (
    <button onClick={() => dispatch(increment())}>
      {value}
    </button>
  )
}

六、Redux 背后的实现原理

1️⃣ Store 是什么?

本质上是:

js
{
  getState,
  dispatch,
  subscribe
}

2️⃣ dispatch 干了什么?

txt
dispatch(action)

rootReducer(currentState, action)

生成 newState

通知所有 subscribers

3️⃣ React-Redux 是如何“精准更新”的?

  • 每个 useSelector 都是一个 subscriber
  • 使用 引用对比 / equalityFn
  • Fiber render 阶段触发更新(而不是 Redux 主动 render)
  • 👉 Redux 不关心 React 怎么更新
  • 👉 React-Redux 不关心 reducer 怎么算

七、异步:为什么用 thunk / createAsyncThunk

Redux 本身只支持同步

txt
dispatch({ type: 'ADD' })

thunk 让 dispatch 支持函数

js
dispatch((dispatch, getState) => {
  setTimeout(() => {
    dispatch(addBy(10))
  }, 1000)
})

RTK 的标准异步方案

js
export const fetchUser = createAsyncThunk(
  'user/fetch',
  async (id) => {
    const res = await fetch(`/api/user/${id}`)
    return res.json()
  }
)

自动生成:

  • pending
  • fulfilled
  • rejected

八、什么时候该用 Redux?

✅ 适合

  • 用户信息 / 权限
  • 全局配置
  • 复杂业务状态机
  • 多页面共享状态

❌ 不适合

  • UI 状态(Modal / Tabs)
  • 表单
  • 简单父子通信