Cannot access 'userSlice' before initialization

Viewed 2872

I am beginner to redux toolkit. I am runnig to this error when I add one more Slice to my application.this is the error in console

I am getting this issue when I added userSlice.ts. Ther was no issues when I added vehicleSlice.ts before that

root-reducee.ts

import { combineReducers } from "@reduxjs/toolkit";
import loaderSlice from "./slices/loaderSlice";
import vehicleSlice from "./slices/vehicleSlice";
import userSlice from "./slices/userSlice";
import snackbarSlice from "./slices/snackbarSlice";
import confirmAlertSlice from "./slices/confirmAlertSlice";

const rootReducer = combineReducers({
  vehicle: vehicleSlice,
  user: userSlice,
  loader: loaderSlice,
  snackbar: snackbarSlice,
  confirm: confirmAlertSlice,
});

export default rootReducer;

userSlice.ts

import { createSlice, PayloadAction } from "@reduxjs/toolkit";

import { AppThunk } from "../index";
import userService from "../../services/userService";
import { startLoading, stopLoading } from "./loaderSlice";
import { User } from "../../types/user";
import { PaginationMeta } from "../../types/pagination-meta";
import { showSnackbar } from "./snackbarSlice";
import { history } from "../../routes";
import routeConstants from "../../constants/route-constants";

export interface IUserListState {
  userList: {
    data: Array<User>;
    meta: PaginationMeta;
    errors: any;
    message: any;
  };
}

const initialState: IUserListState = {
  userList: {
    data: [],
    meta: {
      hasNext: true,
      length: 0,
      took: null,
      total: 0,
    },
    errors: null,
    message: null,
  },
};

export const userSlice = createSlice({
  name: "user",
  initialState,
  reducers: {
    setUserList: (state: any, action: PayloadAction<IUserListState>) => {
      state.userList = action.payload;
    },
  },
});

export const getUserList = (limit: number, offset: number, filter: Partial<User>, searchText : string): AppThunk => async (dispatch) => {
    dispatch(startLoading());
    const response = await userService().getUserList(limit, offset, filter, searchText);
    if (response.data) {
      dispatch(setUserList(response));
    }
    dispatch(stopLoading());
  };


export const saveUser = (user: Partial<User>): AppThunk => async (dispatch) => {
    dispatch(startLoading());
    const response = await userService().saveUser(user);
    if (response.data) {
      dispatch(
        showSnackbar({ snackbarMessage: "Saved", snackbarType: "success" })
      );
      history.push(`${routeConstants.USER}`);
    }
    dispatch(stopLoading());
};


const { actions, reducer } = userSlice;
export const { setUserList } = actions;
export default reducer;

I copied this following slice (vehicle) to create the above slice (user)

vehicleSlice.ts

import { createSlice, PayloadAction } from "@reduxjs/toolkit";

import { AppThunk } from "../index";
import vehicleService from "../../services/vehicleService";
import { startLoading, stopLoading } from "./loaderSlice";
import { Vehicle } from "../../types/vehicle";
import { PaginationMeta } from "../../types/pagination-meta";
import { showSnackbar } from "./snackbarSlice";
import { history } from "../../routes";
import routeConstants from "../../constants/route-constants";

export interface IVehicleListState {
  vehicleList: {
    data: Array<Vehicle>;
    meta: PaginationMeta;
    errors: any;
    message: any;
  };
}

const initialState: IVehicleListState = {
  vehicleList: {
    data: [],
    meta: {
      hasNext: true,
      length: 0,
      took: null,
      total: 0,
    },
    errors: null,
    message: null,
  },
};

export const vehicleSlice = createSlice({
  name: "vehicle",
  initialState,
  reducers: {
    setVehicleList: (state: any, action: PayloadAction<IVehicleListState>) => {
      state.vehicleList = action.payload;
    },
  },
});

export const getVehicleList = (limit: number, offset: number, filter: Partial<Vehicle>, searchText : string): AppThunk => async (dispatch) => {
    dispatch(startLoading());
    const response = await vehicleService().getVehicleList(limit, offset, filter, searchText);
    if (response.data) {
      dispatch(setVehicleList(response));
    }
    dispatch(stopLoading());
  };

export const saveVehicle = (vehicle: Partial<Vehicle>): AppThunk => async (dispatch) => {
    dispatch(startLoading());
    const response = await vehicleService().saveVehicle(vehicle);
    if (response.data) {
      dispatch(
        showSnackbar({ snackbarMessage: "Saved", snackbarType: "success" })
      );
      history.push(`${routeConstants.VEHICLE}`);
    }
    dispatch(stopLoading());
  };

const { actions, reducer } = vehicleSlice;
export const { setVehicleList } = actions;
export default reducer;


snackbarSlice.ts

import { AlertColor } from "@material-ui/core";
import { createSlice } from "@reduxjs/toolkit";

export interface ISnackbarState {
  showSnackbar: boolean;
  snackbarMessage: string;
  snackbarType: AlertColor;
}

const initialState: ISnackbarState = {
  showSnackbar: false,
  snackbarMessage: "",
  snackbarType: "success",
};

export const snackbarSlice = createSlice({
  name: "snackbar",
  initialState,
  reducers: {
    showSnackbar: (state, action: any) => {
      state.showSnackbar = true;
      state.snackbarMessage = action.payload.snackbarMessage;
      state.snackbarType = action.payload.snackbarType;
    },
    hideSnackbar: (state) => {
      state.showSnackbar = false;
      state.snackbarMessage = "";
      state.snackbarType = "success";
    },
  },
});

export const { showSnackbar, hideSnackbar } = snackbarSlice.actions;

export default snackbarSlice.reducer;

loaderSlice.ts

import { createSlice } from "@reduxjs/toolkit";

export interface LoaderState {
  isLoading: boolean;
}

const initialState: LoaderState = {
  isLoading: false,
};

export const loaderSlice = createSlice({
  name: "loader",
  initialState,
  reducers: {
    startLoading: (state) => {
      state.isLoading = true;
    },
    stopLoading: (state) => {
      state.isLoading = false;
    },
  },
});

export const { startLoading, stopLoading } = loaderSlice.actions
export default loaderSlice.reducer

confirmAlertSlice

import { createSlice } from "@reduxjs/toolkit";
import { ReactNode } from "react";

export interface IConfirmAlertState {
  open: boolean;
  title: string;
  description?: string;
  dialogueAction:ReactNode
}

const initialState: IConfirmAlertState = {
  open: false,
  title: "",
  description: "",
  dialogueAction:null
};

export const confirmAlertSlice = createSlice({
  name: "confirm",
  initialState,
  reducers: {
    showConfirm: (state, action: any) => {
      state.open = true;
      state.title = action.payload.title;
      state.description = action.payload.description;
      state.dialogueAction = action.payload.dialogueAction;
    },
    hideConfirm: (state) => {
      state.open = false;
      state.title = "";
      state.description = "";
      state.dialogueAction = null
    },
  },
});

export const { showConfirm, hideConfirm } = confirmAlertSlice.actions;
export default confirmAlertSlice.reducer;


1 Answers

The above error means that you are having a circular dependency issue

Because some other slices was trying to access your userSlice before it was initialized.

You have a few other slices imported in your userSlice and very likely, in those other slices, you have imported them circularly.

You will then need to figure out where is the file import cycle and change it.

Read more here

Related