雜狀態(tài))
React useReducer 復(fù)雜狀態(tài)前置React Context 跨層傳值目標會寫reducer(state, action)理解何時從useState升級。引言一個開關(guān)、一個輸入框 →useState最爽。狀態(tài)字段變多、更新規(guī)則互相牽扯時一堆setX/setY容易亂。useReducer把「怎么從舊狀態(tài)算出新狀態(tài)」收進純函數(shù)reducer(state, action)組件里只dispatch({ type: ... })。本篇 demo計數(shù)器 可調(diào)步長 重置四種 action。動手完整代碼react2/12-usereducer/democdreact2/12-usereducer/demonpminstallnpmrun dev改步長再點step/-step點「重置」回到count0, step1。1. 定義 state / action / reducertype State { count: number; step: number } type Action | { type: inc } | { type: dec } | { type: setStep; step: number } | { type: reset } function reducer(state: State, action: Action): State { switch (action.type) { case inc: return { ...state, count: state.count state.step } case dec: return { ...state, count: state.count - state.step } case setStep: return { ...state, step: action.step } case reset: return { count: 0, step: 1 } default: return state } }約定純函數(shù)同樣輸入 → 同樣輸出不寫副作用不可變更新返回新對象別直接改state.count ...action.type描述「發(fā)生了什么」不是「把 count 設(shè)成幾」2. 組件里dispatchconst [state, dispatch] useReducer(reducer, { count: 0, step: 1 }) button onClick{() dispatch({ type: inc })}step/button button onClick{() dispatch({ type: dec })}-step/button button onClick{() dispatch({ type: reset })}重置/button input typenumber value{state.step} onChange{(e) dispatch({ type: setStep, step: Number(e.target.value) || 1 }) } /UI 只發(fā)意圖怎么改狀態(tài)全在 reducer。3. 何時從 useState 升級繼續(xù) useState考慮 useReducer單個布爾 / 字符串下一狀態(tài)嚴重依賴上一狀態(tài)字段少、更新簡單同一狀態(tài)有多種「動作」想把更新邏輯抽到組件外測useReducer Context 常一起做中等復(fù)雜度的客戶端狀態(tài)更大更碎的全局狀態(tài)看 Zustand15 篇。4. 常見坑做法問題reducer 里fetch/ 改 DOM副作用放錯地方副作用進 event / effect直接 mutatestateReact 可能檢測不到更新action 設(shè)計成「setCount(5)」一堆丟失「意圖」能工作但難推理簡單開關(guān)也上 reducer過度useState更短demo 在練什么手寫State/Action/reducer用dispatch驅(qū)動多動作更新體會「步長影響加減」這種跨字段規(guī)則放在 reducer 里更清晰自己改一改加type: double或把初始 state 換成惰性初始化useReducer(reducer, undefined, init)。下一篇React 嵌套路由與布局