Redux dispatch 与 action 数据流

一句话理解

Store 是状态仓库,你不能直接改它,只能通过发”指令单”(action)让仓库管理员(Reducer)来改。发出指令单这个动作叫 dispatch(派发)


银行账户类比

你(组件) →→ 提交操作单(dispatch action) →→ 柜台人员(Reducer) →→ 更新余额(Store)
  • Store:银行账户余额
  • Action:一张操作单(写着”存款 100 元”)
  • Reducer:柜台工作人员,按操作单规则改余额
  • dispatch:把操作单递给柜台

为什么不能直接改

// 直接改(禁止)
store.balance = 1000
 
// 提交指令单(正确)
dispatch({ type: '存款', payload: 1000 })

因为走 dispatch 有三个好处:

  • 可追踪:每张”指令单”都被记录,DevTools 能看到所有操作历史
  • 可预测:同样的 state + 同样的 action = 永远相同的结果
  • 可撤销:知道每一步做了什么,就能”时间旅行”回退

完整数据流

1. 用户点击按钮
2. dispatch({ type: '存款', payload: 100 })     ← 发出指令单
3. Reducer 收到指令单,计算:0 + 100 = 100       ← 纯函数处理
4. Store 更新:balance = 100                     ← 状态变更
5. 组件自动重新渲染,显示 "余额:100"             ← UI 响应

在代码中的样子

// Reducer:按指令单规则处理
function accountReducer(state = { balance: 0 }, action) {
  switch (action.type) {
    case '存款':
      return { balance: state.balance + action.payload }
    case '取款':
      return { balance: state.balance - action.payload }
    default:
      return state  // 不认识的单子,原样返回
  }
}
 
// 组件:读状态 + 发指令单
function BankApp() {
  const balance = useSelector(state => state.balance)  // 读余额
  const dispatch = useDispatch()                        // 拿到"发单子"的能力
 
  return (
    <div>
      <p>余额:{balance}</p>
      <button onClick={() => dispatch({ type: '存款', payload: 100 })}>
        存 100 元
      </button>
    </div>
  )
}

Saga 里的 put 就是 dispatch

在 Saga 中不能直接调 dispatch,要用 put 代替,效果完全一样:

// 组件里
dispatch({ type: '存款', payload: 100 })
 
// Saga 里(效果一模一样)
yield put({ type: '存款', payload: 100 })

关联知识