Search code examples
reactjstypescriptreduxreact-redux

What is the correct way with Redux to show a method has successfully been called?


I was hoping to call a reducer method in a Redux slice and return true if the logic succeeded and false if it failed but I seem to be getting the following TypeScript error:

Type '(state: WritableDraft, action: { payload: { strategyId: string; stageId: string; }; type: string; }) => boolean' is not assignable to type 'CaseReducer<StrategySlice, { payload: any; type: string; }> | CaseReducerWithPrepare<StrategySlice, PayloadAction<any, string, any, any>>'.

Type '(state: WritableDraft, action: { payload: { strategyId: string; stageId: string; }; type: string; }) => boolean' is not assignable to type 'CaseReducer<StrategySlice, { payload: any; type: string; }>'.

Type 'boolean' is not assignable to type 'void | StrategySlice | WritableDraft'.ts(2322)

My code for the method is below:

const strategySlice = createSlice({
    name: "strategy",
    initialState,
    reducers: {
deleteStage: (state, action: PayloadAction<{ strategyId: string; stageId: string }>): boolean => {
            const { strategyId, stageId } = action.payload;

            const strategyIndex = findStrategyIndexById(state, strategyId);

            if (strategyIndex !== -1) {
                const strategy = state.strategies[strategyIndex];
                strategy.stages = strategy.stages.filter((stage) => stage.id !== stageId);
                return true;
            } else {
                return false;
            }
});

export const {
    deleteStage,
} = strategySlice.actions;
export default strategySlice.reducer;
        },

I'm seeking advice on the best implementation for this. I'm predominantly trying to prevent the method from silently failing, and to implement error handling with this.


Solution

  • Your reducer needs to return an updated state (or void since it is using immer, so changes are tracked).

    Your code returns either true or false.

    Your reducer should be similar to

    deleteStage: (state, action:PayloadAction<{ strategyId: string; stageId: string }>) => {
      const {
        strategyId,
        stageId
      } = action.payload;
    
      const strategyIndex = findStrategyIndexById(state, strategyId);
    
      if (strategyIndex !== -1) {
        const strategy = state.strategies[strategyIndex];
        strategy.stages = strategy.stages.filter((stage) => stage.id !== stageId);
      }
    });