Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

Welcome to Software Development on Codidact!

Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.

Post History

66%
+2 −0
Q&A Redux Toolkit Issue with Managing States

I am all new with using Redux Toolkit, I followed the official documentation to setup the store: // store.ts import { configureStore, ThunkAction, Action, combineReducers } from '@reduxjs/toolkit...

0 answers  ·  posted 10mo ago by boudagga.ma94‭

#2: Nominated for promotion by user avatar Alexei‭ · 2023-07-26T15:19:15Z (10 months ago)
#1: Initial revision by user avatar boudagga.ma94‭ · 2023-07-20T10:31:58Z (10 months ago)
Redux Toolkit Issue with Managing States
I am all new with using Redux Toolkit, I followed the official documentation to setup the **store**:

```
// store.ts
import { configureStore, ThunkAction, Action, combineReducers } from '@reduxjs/toolkit';
import counterReducer from '../features/counter/counterSlice';
import authReducer from '../features/authentication/redux/authSlice';
import delegationReducer from '../features/delegations/redux/delegationSlice'

export const store = configureStore({
  reducer: {
    counter: counterReducer,
    auth: authReducer,
    delegations: delegationReducer
  },
});

export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>;
```

As you can see, I have three reducers: **authReducer**, **delegationReducer** and **counterReducer** which are not related to each other. The issue is when I try to dispatch an action to change the auth state (for example **getAuthenticatedUser()**) all the other reducers partially reset to initial state. The same goes for the other reducers.

I will provide you the code of **authSlice.tsx** and **delegateSlice.tsx** to demonstrate better the problem (I apologize if it is too long):

```
// authSlice.tsx
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios, { AxiosInstance } from "axios";
import { toast } from "react-toastify";

const authInstance: AxiosInstance = axios.create({
  baseURL: "http://localhost:4000/api/auth",
});

interface AuthState {
  token: any;
  isLoading: boolean | null;
  isAuthenticated: boolean | null;
  userData: any;
  error: any;
}

export const registerAdmin = createAsyncThunk(
  "auth/register",
  async (userData: any, { rejectWithValue }) => {
    try {
      const response = await authInstance.post("/register", userData, {
        headers: {
          "Content-Type": "application/json",
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const loginUser = createAsyncThunk(
  "auth/login",
  async (userData: any, { rejectWithValue }) => {
    try {
      const response = await authInstance.post("/", userData, {
        headers: {
          "Content-Type": "application/json",
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const getAuthenticatedUser = createAsyncThunk(
  "auth/get_authenticated_user",
  async (_, { rejectWithValue }) => {
    try {
      const response = await authInstance.get("/", {
        headers: {
          Authorize: localStorage.getItem("auth_token"),
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const requestPasswordChange = createAsyncThunk(
  "auth/request_password_change",
  async (userData: any, { rejectWithValue }) => {
    try {
      const response = await authInstance.post("/password", userData, {
        headers: {
          "Content-Type": "application/json",
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

const initialState = {
  token: localStorage.getItem("auth_token"),
  isLoading: false,
  isAuthenticated: localStorage.getItem("auth_token") !== null,
  error: null,
  userData: null,
} as AuthState;

const authPending = (state: AuthState) => {
  state.isLoading = true;
  state.error = null;
  state.userData = null;
  state.isAuthenticated = false;
};

const authRejected = (state: AuthState, action: any) => {
  localStorage.removeItem("auth_token");
  state.isLoading = false;
  state.error = action.payload;
  state.isAuthenticated = false;
};

export const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    logoutUser(state: AuthState) {
      localStorage.removeItem("auth_token");
      state.isLoading = false;
      state.error = null;
      state.isAuthenticated = false;
      state.userData = null;
    }
  },
  extraReducers: (builder) => {
    builder
      .addCase(registerAdmin.pending, authPending)
      .addCase(loginUser.pending, authPending)
      .addCase(getAuthenticatedUser.pending, authPending)
      .addCase(requestPasswordChange.pending, authPending)
      .addCase(registerAdmin.rejected, authRejected)
      .addCase(loginUser.rejected, authRejected)
      .addCase(getAuthenticatedUser.rejected, authRejected)
      .addCase(requestPasswordChange.rejected, authRejected)
      .addCase(registerAdmin.fulfilled, (state: AuthState, { payload }) => {
        state.isLoading = false;
        state.isAuthenticated = true;
        state.userData = null;
        state.error = null;
        localStorage.setItem("auth_token", payload.token);
      })
      .addCase(loginUser.fulfilled, (state: AuthState, { payload }) => {
        state.isLoading = false;
        state.isAuthenticated = true;
        state.userData = null;
        state.error = null;
        localStorage.setItem("auth_token", payload.token);
      })
      .addCase(
        getAuthenticatedUser.fulfilled,
        (state: AuthState, { payload }) => {
          state.isLoading = false;
          state.isAuthenticated = true;
          state.userData = payload;
          state.error = null;
          state.token = localStorage.getItem("auth_token");
        }
      )
      .addCase(
        requestPasswordChange.fulfilled,
        (state: AuthState, { payload }) => {
          state.isLoading = false;
          state.isAuthenticated = false;
          state.userData = false;
          state.error = null;
          state.token = localStorage.getItem("auth_token");
        }
      )
      .addDefaultCase((state: AuthState) => {
        state.token = localStorage.getItem("auth_token");
        state.isLoading = false;
        state.isAuthenticated = localStorage.getItem("auth_token") ? true : false
        state.error = null;
        state.userData = null;
      });
  },
});

export const { logoutUser } = authSlice.actions;

export default authSlice.reducer;

// delegationSlice.tsx
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import axios, { AxiosInstance } from "axios";
import { toast } from "react-toastify";

const delegationsInstance: AxiosInstance = axios.create({
  baseURL: "http://localhost:4000/api/delegations",
});

interface DelegationsState {
  delegationList: any;
  delegateList: any;
  delegationData: any;
  delegateData: any;
  isLoading: boolean | null;
  error: any;
  storedDelegationData: any;
}

export const addDelegation = createAsyncThunk(
  "delegations/add_delegation",
  async (delegationData: any, { rejectWithValue }) => {
    try {
      const response = await delegationsInstance.post("/", delegationData, {
        headers: {
          "Content-Type": "application/json",
          Authorize: localStorage.getItem("auth_token"),
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const addDelegate = createAsyncThunk(
  "delegations/add_delegate",
  async (data: any, { rejectWithValue }) => {
    const { delegationId, delegateData } = data;
    try {
      const response = await delegationsInstance.post(
        `/delegates/${delegationId}`,
        delegateData,
        {
          headers: {
            "Content-Type": "application/json",
            Authorize: localStorage.getItem("auth_token"),
          },
        }
      );
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const getDelegationList = createAsyncThunk(
  "delegations/get_delegation_list",
  async (_, { rejectWithValue }) => {
    try {
      const response = await delegationsInstance.get("/delegations", {
        headers: {
          Authorize: localStorage.getItem("auth_token"),
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const getDelegation = createAsyncThunk(
  "delegations/get_delegation",
  async (data: any, { rejectWithValue }) => {
    const { id } = data;
    try {
      const response = await delegationsInstance.get(`/delegations/${id}`, {
        headers: {
          Authorize: localStorage.getItem("auth_token"),
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const getDelegateList = createAsyncThunk(
  "delegations/get_delegate_list",
  async (_, { rejectWithValue }) => {
    try {
      const response = await delegationsInstance.get("/delegates", {
        headers: {
          Authorize: localStorage.getItem("auth_token"),
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const getDelegate = createAsyncThunk(
  "delegations/get_delegate",
  async (data: any, { rejectWithValue }) => {
    const { id } = data;
    try {
      const response = await delegationsInstance.get(`/delegates/${id}`, {
        headers: {
          Authorize: localStorage.getItem("auth_token"),
        },
      });
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const updateDelegation = createAsyncThunk(
  "delegations/update_delegation",
  async (data: any, { rejectWithValue }) => {
    const { id, delegationData } = data;
    try {
      const response = await delegationsInstance.put(
        `/delegations/${id}`,
        delegationData,
        {
          headers: {
            "Content-Type": "application/json",
            Authorize: localStorage.getItem("auth_token"),
          },
        }
      );
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const updateDelegate = createAsyncThunk(
  "delegations/update_delegate",
  async (data: any, { rejectWithValue }) => {
    const { id, delegateData } = data;
    try {
      const response = await delegationsInstance.put(
        `/delegates/${id}`,
        delegateData,
        {
          headers: {
            "Content-Type": "application/json",
            Authorize: localStorage.getItem("auth_token"),
          },
        }
      );
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const removeDelegation = createAsyncThunk(
  "delegations/remove_delegation",
  async (data: any, { rejectWithValue }) => {
    const { id } = data;
    try {
      const response = await delegationsInstance.put(
        `/delegations/remove/${id}`,
        {
          headers: {
            Authorize: localStorage.getItem("auth_token"),
          },
        }
      );
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

export const removeDelegate = createAsyncThunk(
  "delegations/remove_delegate",
  async (data: any, { rejectWithValue }) => {
    const { id } = data;
    try {
      const response = await delegationsInstance.put(
        `/delegates/remove/${id}`,
        {
          headers: {
            Authorize: localStorage.getItem("auth_token"),
          },
        }
      );
      return response.data;
    } catch (error: any) {
      const errorMessages = error?.response?.data?.errors?.map(
        (err: any) => err.msg
      );
      toast.error(errorMessages?.join("\n"));
      return rejectWithValue(error.response.data);
    }
  }
);

const initialState = {
  delegationList: [],
  delegateList: [],
  delegationData: null,
  delegateData: null,
  isLoading: false,
  error: null,
  storedDelegationData: null,
} as DelegationsState;

const delegPending = (state: DelegationsState) => {
  state.isLoading = true;
  state.error = null;
};

const delegRejected = (state: DelegationsState, action: any) => {
  state.isLoading = false;
  state.error = action.payload;
};

export const delegationSlice = createSlice({
  name: "delegations",
  initialState,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(addDelegation.pending, delegPending)
      .addCase(addDelegate.pending, delegPending)
      .addCase(getDelegationList.pending, delegPending)
      .addCase(getDelegateList.pending, delegPending)
      .addCase(getDelegation.pending, delegPending)
      .addCase(getDelegate.pending, delegPending)
      .addCase(updateDelegation.pending, delegPending)
      .addCase(updateDelegate.pending, delegPending)
      .addCase(removeDelegation.pending, delegPending)
      .addCase(removeDelegate.pending, delegPending)
      .addCase(addDelegation.rejected, delegRejected)
      .addCase(addDelegate.rejected, delegRejected)
      .addCase(getDelegationList.rejected, delegRejected)
      .addCase(getDelegateList.rejected, delegRejected)
      .addCase(getDelegation.rejected, delegRejected)
      .addCase(getDelegate.rejected, delegRejected)
      .addCase(updateDelegation.rejected, delegRejected)
      .addCase(updateDelegate.rejected, delegRejected)
      .addCase(removeDelegation.rejected, delegRejected)
      .addCase(removeDelegate.rejected, delegRejected)
      .addCase(
        addDelegation.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = [...state.delegationList, payload];
          state.delegateList = [];
          state.delegationData = null;
          state.delegateData = null;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addCase(
        addDelegate.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = [];
          state.delegateList = [...state.delegateList, payload];
          state.delegationData = null;
          state.delegateData = null;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addCase(
        getDelegationList.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = payload;
        }
      )
      .addCase(
        getDelegateList.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = [];
          state.delegateList = payload;
          state.delegationData = null;
          state.delegateData = null;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addCase(
        getDelegation.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = [];
          state.delegateList = [];
          state.delegationData = payload;
          state.delegateData = null;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addCase(
        getDelegate.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = [];
          state.delegateList = [];
          state.delegationData = null;
          state.delegateData = payload;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addCase(
        updateDelegation.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = state.delegationList.map((el: any) =>
            el._id === payload._id ? payload : el
          );
          state.delegateList = [];
          state.delegationData = null;
          state.delegateData = null;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addCase(
        removeDelegation.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = state.delegationList.map((el: any) =>
            el._id === payload._id ? payload : el
          );
          state.delegateList = [];
          state.delegationData = null;
          state.delegateData = null;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addCase(
        updateDelegate.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = [];
          state.delegateList = state.delegateList.map((el: any) =>
            el._id === payload._id ? payload : el
          );
          state.delegationData = null;
          state.delegateData = null;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addCase(
        removeDelegate.fulfilled,
        (state: DelegationsState, { payload }) => {
          state.isLoading = false;
          state.delegationList = [];
          state.delegateList = state.delegateList.map((el: any) =>
            el._id === payload._id ? payload : el
          );
          state.delegationData = null;
          state.delegateData = null;
          state.error = null;
          state.storedDelegationData = null;
        }
      )
      .addDefaultCase((state: DelegationsState) => {
        state.isLoading = false;
        state.delegationList = [];
        state.delegateList = [];
        state.delegationData = null;
        state.delegateData = null;
        state.error = null;
        state.storedDelegationData = null;
      });
  },
});

export const {} = delegationSlice.actions;

export default delegationSlice.reducer;

```

As you can see, the two slices are independent of each other, when I try to dispatch getDelegationList(), I get successfully the list of delegations but userData becomes null (isAuthenticated still true and there is a token in the local storage). when I try to dispatch getAuthenticatedUser(), I get successfully the user data but the delegation list becomes `[]`.

What causes this problem and how to fix it ?