Redux Toolkit中间件使用问题:checkWinner逻辑移入报错
问题解决:Redux Toolkit中checkWinner逻辑的重构与报错修复
错误原因分析
你遇到的getState is not a function报错,核心问题有三个:
- 把Thunk Action Creator当成中间件添加:你写的
checkWinner是Thunk异步Action Creator,不是Redux中间件本身。Redux Toolkit的getDefaultMiddleware已经内置了Thunk中间件,不需要手动把这个函数加到middleware数组里。 - 状态获取路径错误:
getState()返回整个根状态对象,直接解构roundEnd取不到对应值,需要从game切片里获取状态。 - Store配置与payload格式错误:
configureStore的reducer字段需要传入切片的reducer属性(即gameSlice.reducer)而非切片本身;另外setWinner的payload需要是包含winner的对象,而非字符串。
修正后的代码实现
1. 重构Game Slice
删掉原切片里的checkWinner reducer,保留基础状态更新Action:
const gameSlice = createSlice({ name: 'game', initialState: { roundEnd: null, score: { computer: 0, player: 0 }, usedCells: [], winCell: null, // 其他状态字段 }, reducers: { setRoundEnd: (state, action) => { state.roundEnd = action.payload; }, setWinner: (state, action) => { if (action.payload.winner === 'computer') { state.score.computer += 1; state.usedCells.splice( state.usedCells.indexOf(state.winCell), 1, -state.winCell ); } if (action.payload.winner === 'player') { state.score.player += 1; } }, } }); // 导出基础Action Creator export const { setRoundEnd, setWinner } = gameSlice.actions; // 导出切片reducer供Store使用 export default gameSlice.reducer;
2. 正确编写Thunk Action Creator
把原checkWinner的逻辑改成Thunk,用于主动触发状态检查与更新:
export const checkWinner = () => (dispatch, getState) => { // 从根状态中获取game切片的状态 const { game } = getState(); const { roundEnd } = game; if (roundEnd === null || roundEnd) { dispatch(setRoundEnd(false)); } else { // 传入符合setWinner要求的payload格式 dispatch(setWinner({ winner: 'computer' })); } };
3. 正确配置Store
无需额外添加自定义中间件,使用默认配置即可:
import { configureStore } from '@reduxjs/toolkit'; import gameReducer from './gameSlice'; export const store = configureStore({ reducer: { game: gameReducer // 这里传入切片的reducer }, // 无需手动添加Thunk,默认已包含 middleware: getDefaultMiddleware => getDefaultMiddleware(), });
组件中使用方式
在React组件中通过useDispatch触发这个Thunk:
import { useDispatch } from 'react-redux'; import { checkWinner } from './path/to/store'; function GameComponent() { const dispatch = useDispatch(); const handleCheckWinner = () => { dispatch(checkWinner()); }; return ( <button onClick={handleCheckWinner}> 检查当前回合胜负 </button> ); }
可选:用自定义中间件自动触发(如果需要)
如果希望在某个特定Action触发时自动执行胜负检查,可以编写自定义中间件:
const checkWinnerMiddleware = store => next => action => { // 监听某个Action,比如玩家落子完成的Action if (action.type === 'game/playerMoveCompleted') { const { game } = store.getState(); const { roundEnd } = game; if (roundEnd === null || roundEnd) { store.dispatch(setRoundEnd(false)); } else { store.dispatch(setWinner({ winner: 'computer' })); } } // 继续传递Action到下一个中间件或Reducer return next(action); }; // 配置Store时添加这个中间件 export const store = configureStore({ reducer: { game: gameReducer }, middleware: getDefaultMiddleware => getDefaultMiddleware().concat(checkWinnerMiddleware), });
内容的提问来源于stack exchange,提问作者JohnyPlay
相关产品推荐
相关产品推荐

