Search code examples
reactjsreduxredux-thunkredux-toolkitrtk-query

RTK Query get state from another slice using getState()


I just started on redux yesterday and after reading up on the different libraries, I decided to use the slice route from RTK.

For my async, instead of using createAsyncThunk, I decided to use RTK query and I have a question on the right way to access state from another slice.

slice1 contains some user data for example:

export const initialState: IUserState = {
   name: 'example',
   id: null,
};

and in my slice2, I have a function that wants to do something like getSomethingByUserId(id) and my current implementation:

interface IApiResponse {
  success: true;
  result: IGotSomethingData[];
}

const getsomethingSlice: any = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({
    baseUrl: 'https://someapibase',
  }),
  endpoints(builder) {
    return {
      fetchAccountAssetsById: builder.query<IApiResponse, null>({
        query() {
          console.log('store can be called here', store.getState().user.id);
          return `/apipath?id=${store.getState().user.id}`;
        },
      }),
    };
  },
});

export default getsomethingSlice;
export const { useFetchAccountAssetsByIdQuery } = getsomethingSlice;

As I read somewhere that markerikson mentioned it's not good practice to import the store but to use getState in thunk, I took a look around and see in the documentations that there is getState for query which exist in the onStart unlike thunk which you can access it from it's second parameter.

Do anyone have a onStart implementation for this? Or is importing store acceptable for this?


Solution

  • Generally, we want to prevent people from doing that, which is why you don't have getStore available there (you have at many other places).

    You see, RTK-query uses the argument you give into the query to determine the cache key. Since you don't pass in an argument, the cache key the result would be stored as fetchAccountAssetsById(undefined).

    So, you make a first request, state.user.id is 5 and that request is made.

    Now, your state.user.id changes to 6. But your component calls useFetchAccountAssetsByIdQuery() and there is already a cache entry for fetchAccountAssetsById(undefined), so that is still being used - and no request is made.

    If your component instead would be calling useFetchAccountAssetsByIdQuery(5) and it changes to useFetchAccountAssetsByIdQuery(6), RTK-query can safely identify that it has a cache entry for fetchAccountAssetsById(5), but not for fetchAccountAssetsById(6) and will make a new request, retrieving up-to-date information.

    So, you should select that value in your component using useSelector and pass it into your query hook as an argument, not pull it out of the store in your query function.