reduxjs / redux-toolkit

The official, opinionated, batteries-included toolset for efficient Redux development
https://redux-toolkit.js.org
MIT License
10.7k stars 1.17k forks source link

ReferenceError: Cannot access 'api' before initialization #2153

Closed dropocol closed 2 years ago

dropocol commented 2 years ago

I am having trouble catching the action generated from the injectEndpoints from the workspace api in my userSlice using the extraReducers.

My code structure is as follow.

baseApi src/redux/services/api

export const api = createApi({
  reducerPath: "api",
  baseQuery: baseQueryWithReauth,
  endpoints: (builder) => ({
  }),
});

Workspace src/redux/services/workspace

export const workspace = api.injectEndpoints({
  endpoints: (builder) => ({
    getDocs: builder.query<any, void>({
      query: () => `/workspace/6236f159662bebb0c2669430/docs`,
    }),
  }),
});

export const { useGetDocsQuery } = workspace;

User Slice src/redux/splices/user

const userSlice = createSlice({
  name: "user",
  initialState: { user: null } as UserState,
  reducers: {
    setUser: (state, action) => {
      state.user = action.payload.user;
    },
    loggedOut: (state) => {
      state.user = null;
    },
  },
  extraReducers: (builder) => {
    builder.addMatcher(
      workspace.endpoints.getDocs.matchFulfilled,
      (state, { payload }) => {
        console.log(payload);
      }
    );
  },
});

The error : ReferenceError: Cannot access 'api1' before initialization This Line : export const workspace = api.injectEndpoints({

If I put the code from the workspace api directly under the baseApi, it works without any issues so I am not sure how to solve this problem.

Edit : It looks like a circular dependency but I can't seem to figure out how to sole it if the code is in another file.

markerikson commented 2 years ago

Closing as this isn't an issue with RTK itself.

silent-tan commented 2 years ago

I also meet this error image

image
phryneas commented 2 years ago

@silent-tan my crystal ball says you are doing baseQuery: baseQueryWithReauth() instead of baseQuery: baseQueryWithReauth

silent-tan commented 2 years ago

just the code like https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#automatic-re-authorization-by-extending-fetchbasequery

it works if remove

api.dispatch(logout())

maybe works if not use injectEndpoints api

phryneas commented 2 years ago

The error is how you call baseQueryWithReauth in your createApi call and you are not sharing that. :crystal_ball: :crystal_ball: :crystal_ball:

progtarek commented 1 year ago

I am facing the same issue and I believe this is because using injectEndpoints for sub-modules which has the logout setup. @silent-tan
Did you manage to fix it?

silent-tan commented 1 year ago

No, i had solved this problem by subscribing in extraReducer

karanshah229 commented 1 year ago

I am facing the same issue. I have a rootApi into which I injectEndpoints. I have extended fetchBaseQuery to handle JWT Authentication and am using baseQuery: baseQueryWithReAuth correctly.

@silent-tan @phryneas can you explain your solution to this problem.

pierregambaud commented 1 year ago

@karanshah229 did you find a solution? I am facing the same error.

I call baseQuery: baseQueryWithReauth like this:

export const rootAPI = createApi({
  reducerPath: "rootAPI",
  baseQuery: baseQueryWithReauth,
  endpoints: () => ({}),
});

My baseQueryWithReauth looks like the one in the doc: https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#automatic-re-authorization-by-extending-fetchbasequery

The api.dispatch(loggedOut()) part is linked to the error.

Any idea on how to solve it?

UPDATE with solution 👇

Instead of using api.dispatch(loggedOut()), you should write api.dispatch({ type: "auth/loggedOut" }).

Same if you are using api.dispatch(refreshToken(token)), write this api.dispatch({ type: "auth/refreshToken", payload: token })

Many thanks to @Rodrigo-JM for sharing the solution in this discussion: https://github.com/reduxjs/redux-toolkit/discussions/2097#discussioncomment-3079703

kosChupahin commented 8 months ago

Faced with the same problem when decided to add extraReducers to userSlice. Updated imports order in store.ts file and it helped)

before

import { api } from '@/api';
import userReducer from '@/store/features/userSlice';
.....

const rootReducer: any = combineReducers({
  [api.reducerPath]: api.reducer,
  userState: userReducer
});

after

import userReducer from '@/store/features/userSlice';
import { api } from '@/api';
belackriv commented 8 months ago

Thanks @kosChupahin , I'm sure I would have tried this eventually, but was a lot quicker to read the comment and see that's exactly what I had done as well.

jonaldinger commented 3 weeks ago

In my case this error was caused by a circular dependency in my codebase that had nothing to do with RTK specifically. I was clued into this by @dropocol's "edit" comment at the bottom of his original post, so I ran a circular dependency checker on my codebase (Madge is the one I used - madge --circular path/src/app.js). It found a few, I went straight for the one involving a slice file, and the error went away as soon as I resolved the circular dependency.