Cannot access 'userSlice' before initialization
Asked Answered
W

4

6

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;


Wheeler answered 4/9, 2021 at 4:24 Comment(0)
P
6

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

Perspicacity answered 4/9, 2021 at 4:33 Comment(4)
I have added all other Slices to the question. none of them have imported useSlice - @ryan-leWheeler
May I have access to your repository?Perspicacity
I changes order of imports of my action creators from userSlice.ts in my component, and the issue were gone. Thanks..!Wheeler
I had an entirely different issue but got similar error based on same concept. Lesson to be learnt: If you get an error "Cannot access 'xyz' before initialization" it will most likely mean there's a circular dependency preventing a variable to be initialized. Thanks for the answer!Caroylncarp
S
1

I had the same problem today, It was problem from Barrel files (index.js)

Scuta answered 1/2, 2023 at 23:24 Comment(2)
Hi, could you please specify what was the problem in Barrel files? How to give good answerMasto
@Masto sorry, I forgot to mention what was the problem, I made one barrel file for the whole store folder (exporting slices subdirectories inside), but this error were appears, so I changed imports directly to slices that I was trying to use, instead using whole store importLampoon
B
0

I had the same problem, I solved it by moving the store-related logic into a sub component and not into the page.tsx file

Balderas answered 16/9, 2023 at 13:8 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Kabuki
P
-1

I solved this by changing the import order in one of the components

Pavier answered 20/9 at 12:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.