reactjslaravelreduxredux-toolkitinertiajs

Inertiajs onFinish not working in redux toolkit reducer


When I logout in the popup appears for confirmation when I click on it and out of the session it is fine the problem is when I register or sign in again the (isLogouting and isOpeLogoutDialogue) do not change to false. i provide all of the configure code about redux toolkit

import { createSlice } from "@reduxjs/toolkit";
import GlobalReducer from "./GlobalReducer";
import GlobalStates from "./GlobalStates";

const GlobalSlice = createSlice({
    name: "global",
    initialState: GlobalStates,
    reducers: GlobalReducer,
});

export default GlobalSlice.reducer;
export const {
    handleOpenLogoutDialogue,
    handleCloseLogoutDialogue,
    handleLoggedOut,
} = GlobalSlice.actions;

const GlobalStates = {
    isOpeLogoutDialogue: false,
    isLogOuting: false,
};

export default GlobalStates;

      
  import { router } from "@inertiajs/react";
    
    const GlobalReducer = {
        handleLoggedOut(state, action, dispatch) {
            state.isLogOuting = true;
            router.post(route("logout"), {
                onFinish: () => {
                    state.isLogOuting = false;
                    state.isOpeLogoutDialogue = false;
                },
            });
        },
        handleOpenLogoutDialogue(state, action) {
            state.isOpeLogoutDialogue = true;
        },
        handleCloseLogoutDialogue(state, action) {
            state.isOpeLogoutDialogue = false;
        },
    };
    
    export default GlobalReducer;
    import { configureStore } from "@reduxjs/toolkit";
import AuthReducer from "./Slices/Auth/AuthSlice";
import GlobalReducer from "./Slices/Global/GlobalSlice";

const store = configureStore({
    reducer: {
        auth: AuthReducer,
        global: GlobalReducer,
    }
});

export default store;

Solution

  • Reducers are pure functions, they can't call router.post and try to apply any asynchronous logic. The onFinish should dispatch actions to the store to effect any state changes.

    I suggest refactoring this logic into an asynchronous action that can (a) apply asynchronous logic and (b) dispatch actions back to the store via the generated pending/fulfilled/rejected actions for you to handle in extra reducers.

    Basic Example:

    import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
    import { router } from "@inertiajs/react";
    import GlobalStates from "./GlobalStates";
    
    export const handleLoggedOut = createAsyncThunk(
      "global/handleLoggedOut",
      () => {
        return new Promise((resolve => {
          router.post(route("logout"), {
            onFinish: resolve,
          });
        }))
      }
    );
    
    const GlobalSlice = createSlice({
      name: "global",
      initialState: GlobalStates,
      reducers: {
        handleOpenLogoutDialogue(state) {
          state.isOpeLogoutDialogue = true;
        },
        handleCloseLogoutDialogue(state) {
          state.isOpeLogoutDialogue = false;
        },
      },
      extraReducers: builder => {
        builder
          .addCase(handleLoggedOut.pending, () => {
            state.isLogOuting = true;
          })
          .addCase(handleLoggedOut.fulfilled, () => {
            state.isLogOuting = false;
            state.isOpeLogoutDialogue = false;
          })
          .addCase(handleLoggedOut.rejected, () => {
            state.isLogOuting = false;
            state.isOpeLogoutDialogue = false;
          });
      },
    });
    
    export const {
      handleOpenLogoutDialogue,
      handleCloseLogoutDialogue,
    } = GlobalSlice.actions;
    
    export default GlobalSlice.reducer;