You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Redux Toolkit中间件使用问题:checkWinner逻辑移入报错

问题解决:Redux Toolkit中checkWinner逻辑的重构与报错修复

错误原因分析

你遇到的getState is not a function报错,核心问题有三个:

  1. 把Thunk Action Creator当成中间件添加:你写的checkWinner是Thunk异步Action Creator,不是Redux中间件本身。Redux Toolkit的getDefaultMiddleware已经内置了Thunk中间件,不需要手动把这个函数加到middleware数组里。
  2. 状态获取路径错误:getState()返回整个根状态对象,直接解构roundEnd取不到对应值,需要从game切片里获取状态。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 03:55:14