Home > Software design >  How to work with middlewares in redux toolkit?
How to work with middlewares in redux toolkit?

Time:01-24

I'm using slices in redux toolkit. In one of slice's action i have code that is duplicated from other actions because in actions you can't call another actions.

I want to put all the logic of this action checkWinner into middleware, but I can’t do this in the redux toolkit in configureStore. In checkWinner i need actual state.

And, probably, I do not fully understand how to create such middleware.

This is my Slice:

const gameSlice = createSlice({
    name: 'game',
    initialState: {
        roundEnd: 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;
            }
        },
        checkWinner: (state) => {
            if (state.roundEnd === null || state.roundEnd) {
                state.roundEnd = false;
            } else {
                state.score.computer  = 1;

                state.usedCells.splice(
                    state.usedCells.indexOf(state.winCell),
                    1,
                    -state.winCell
                );
            }
        }
    }
}

In store i'm tried:

export const checkWinner = () => (dispatch, getState) => {
    const { roundEnd } = getState(); 

    if (roundEnd === null || roundEnd) {
        dispatch(setRoundEnd(false));
    } else {
        dispatch(setWinner('computer'));
    }
}

export const store = configureStore({
    reducer: {game: gameSlice},
    middleware: getDefaultMiddleware => getDefaultMiddleware().concat(checkWinner)
});

But it doesn't work. Error: getSTate is not a function.

CodePudding user response:

Your middleware is written incorrectly. The correct signature would be:

// Outer function: gets {dispatch, getState}
const SomeMiddleware = (storeApi) => {
  // Middle function: gets the "next" middleware in the pipeline
  return (next) => {
    // Inner function: gets the current action
    return (action) => {
      return next(action);
    }
  }
}

Additionally, your getState call is wrong, because you're trying to read state.roundEnd. However, the roundEnd field is part of the game slice of state, so it really should be state.game.roundEnd.

  • Related