'Refactoring thunk slices to RTK-Query causing top-level API calls invalid

I'm working on an app using react / redux / redux-toolkit.

Until now, I was using createAsyncThunk to wrap API calls, but for more convenience I decided to use RTK-Query.

It works fine in most cases. However, there's a situation in which I'm unable to make it work. This is when I want the API call to be done directly at the app startup, in the index.js file, as follows :

Working version :

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from "react-redux";

import App from './App';
import store from './store';
import {fetchUserInfo} from "./features/user";

store.dispatch(fetchUserInfo());

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>
    , document.getElementById('root')
);

Here, the store.dispatch(fetchUserInfo()); is placed here so that store.user.info will be available in any subsequent component.

The definition of the fetchUserInfo() is made here :

features/user.js

import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import {apiCall} from "./utils";

export const fetchUserInfo = createAsyncThunk(
    'user/info',
    async (thunkAPI) => {
        const res = await apiCall('https://my.api/userinfo').json();
        return res;
    });


export const userSlice = createSlice({
    name: 'user',
    initialState: { info: '' },
    reducers: {},
    extraReducers: (builder) => {
        builder
        .addCase(fetchUserInfo.fulfilled, (state, action) => {
            state.info = action.payload;
        })
    },
});

export default userSlice.reducer;

What I would like to do is replace this slice by something like that :

Errored Version :

api/user.js

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

const rawBaseQuery = (baseUrl) => fetchBaseQuery({
    baseUrl,
    prepareHeaders: (headers, {getState}) => {
        headers.set('Authorization', '*******');
        return headers
    }
});

export const baseQuery = async (args, api, extraOptions) => {
    const baseUrl = api.getState().api.root; // 'https://my.api'
    return rawBaseQuery(baseUrl)(args, api, extraOptions);
};

export const userApi = createApi({
    reducerPath: 'user',
    baseQuery: baseQuery,
    endpoints: (builder) => ({
        getUserInfo: builder.query({
            query: () => `/userinfo`
        }),
    }),
});
    
export const {
    useGetUserInfoQuery
} = userApi;

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from "react-redux";

import App from './App';
import store from './store';
import {useGetUserInfoQuery} from "./api/user";

store.dispatch(useGetUserInfoQuery());

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>
    , document.getElementById('root')
);

But, I can not call useGetUserInfoQuery() in ìndex.js. The following error occurs :

React Hook use query cannot be called at the top level.

I also tried to call useGetUserInfoQuery() without dispatch but the same error occurs.

How should I proceed? Thanks!



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source