雜狀態(tài))
React useReducer 復(fù)雜狀態(tài)前置React Context 跨層傳值目標(biāo)會(huì)寫(xiě)reducer(state, action)理解何時(shí)從useState升級(jí)。引言一個(gè)開(kāi)關(guān)、一個(gè)輸入框 →useState最爽。狀態(tài)字段變多、更新規(guī)則互相牽扯時(shí)一堆setX/setY容易亂。useReducer把「怎么從舊狀態(tài)算出新?tīng)顟B(tài)」收進(jìn)純函數(shù)reducer(state, action)組件里只dispatch({ type: ... })。本篇 demo計(jì)數(shù)器 可調(diào)步長(zhǎng) 重置四種 action。動(dòng)手完整代碼react2/12-usereducer/democdreact2/12-usereducer/demonpminstallnpmrun dev改步長(zhǎng)再點(diǎn)step/-step點(diǎn)「重置」回到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ù)同樣輸入 → 同樣輸出不寫(xiě)副作用不可變更新返回新對(duì)象別直接改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. 何時(shí)從 useState 升級(jí)繼續(xù) useState考慮 useReducer單個(gè)布爾 / 字符串下一狀態(tài)嚴(yán)重依賴上一狀態(tài)字段少、更新簡(jiǎn)單同一狀態(tài)有多種「動(dòng)作」想把更新邏輯抽到組件外測(cè)useReducer Context 常一起做中等復(fù)雜度的客戶端狀態(tài)更大更碎的全局狀態(tài)看 Zustand15 篇。4. 常見(jiàn)坑做法問(wèn)題reducer 里fetch/ 改 DOM副作用放錯(cuò)地方副作用進(jìn) event / effect直接 mutatestateReact 可能檢測(cè)不到更新action 設(shè)計(jì)成「setCount(5)」一堆丟失「意圖」能工作但難推理簡(jiǎn)單開(kāi)關(guān)也上 reducer過(guò)度useState更短demo 在練什么手寫(xiě)State/Action/reducer用dispatch驅(qū)動(dòng)多動(dòng)作更新體會(huì)「步長(zhǎng)影響加減」這種跨字段規(guī)則放在 reducer 里更清晰自己改一改加type: double或把初始 state 換成惰性初始化useReducer(reducer, undefined, init)。下一篇React 嵌套路由與布局