RTK Query query not refetching after mutation
Asked Answered
N

3

7

On my api I have two mutations and strangely, one of them does trigger the refetch but the other doesn't and I have no clue why. Both mutations make their networks calls and changes are reflected in the server.

Here's my api definition.

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/dist/query/react";
import Sample from "core/types/Sample";
import getApiURL from "core/utils/getApiURL";

export const lithologyApi = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: getApiURL() }),
  tagTypes: ["Samples"],
  endpoints: build => ({
    addSample: build.mutation<Sample, Sample>({
      query: sample => ({
        url: `lithology/add-sample`,
        method: "POST",
        body: sample,
      }),
      invalidatesTags: ["Samples"],
    }),
    getSamples: build.query<Sample[], void>({
      query: () => "lithology/get-samples",
      providesTags: ["Samples"],
    }),
    deleteSample: build.mutation<void, number>({
      query: id => ({ url: `lithology/delete-sample/${id}`, method: "DELETE" }),
      invalidatesTags: ["Samples"],
    }),
  }),
});

export const {
  useAddSampleMutation,
  useGetSamplesQuery,
  useDeleteSampleMutation,
} = lithologyApi;

I don't know if it's relevant but the mutation that succesfully invalidates (addSample) it's in a different component, while the one that doesn't (deleteSample) it's in the same (I've already tried moving it to another component and it didn't work anyways).

Nous answered 28/6, 2021 at 15:23 Comment(6)
Hmm. Generally: change the import to "@reduxjs/toolkit/query/react" but that won't solve the problem. Are all of these really in one createApi call or did you simplify that for the Stackoverflow question? Also, just to make sure: the middleware is registered?Highpriced
Yes, that's all there is for that createApi call and yes, the middleware is registered. I mean, the deleteSample mutation callback makes the network request, it just doesn't trigger the invalidation for getSamples (which addSamples does).Nous
If the middleware were not registered, it would still make the network request, but not trigger invalidation, that's why I was asking.Highpriced
Do you get a completely empty response back? And can you check if your mutation actually goes into an isError state? I have an assumption.Highpriced
Because I was in a hurry, I ended doing things how I was doing them before, so I don't have that code available anymore. I'll definitely try it on with any new project I have and thank you very much for helping :)Nous
In my case it was case mentioned by @FooBar, tho I had to add thunk before this middlewareBanc
H
2

So, just to give an answer here so that someone else can maybe use it:

I assume that your deleteSample endpoint was giving an empty response. Per default, fetchBaseQuery's responseHandler is set to json, so it tries to JSON.parse an empty string - and crashes with an unhandled error.

Uncaught SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data

Now, invalidateTags is only called on success and for handled errors, but not in the case of an unhandled error, since that would lead to all kinds of inpredictable behaviour in case your invalidateTags was not an array, but a function.

Long story short: In your request, set responseHandler to text or a custom function.

Also, always read errors - when you read that error above getting back from your hook, it should already become pretty obvious :)

Highpriced answered 29/6, 2021 at 21:33 Comment(5)
This sounds like the most likely case, however I don't remember ever seeing any unhandled error on console. I'll try testing if this is the case and I wonder if it might be useful to change parts of the question to match more specifically the problem, so people find it easier.Nous
Even unhandled, it would end up in the error field of the hook, not on the console.Highpriced
This helped me on my issue on using SWAPI's wookie format. Indeed, the responseHandler does a JSON.parse under the hood. And in my case, I am using ngrx-rtk-query for my ng project. When the handler fails to parse the data, error is caught internally and transformResponse is simply not invoked.Cavalcade
Updating to Redux Toolkit 1.6.1 should give you a much more descriptive error and any unhandled error will also be printed to the console.Highpriced
Thank you, this really solved my issue! Turns out my mutation was expecting a response from the server with a generics like <Post, Post>, so changing it to <void, Post> resolved the issue, since API doesn't provide any response :)Amongst
V
2

In my case it was related to not adding the middleware to configureStore.

export const lithologyApi = createApi({
// ....
});

const store = configureStore({
    // ....

    // Adding the api middleware enables caching, invalidation, polling,
    // and other useful features of `rtk-query`.
    middleware: [
        lithologyApi.middleware,
    ],
});
Vase answered 6/10, 2021 at 15:57 Comment(0)
L
0

Try adding the next function to the file and replace the providedTags in getSamples query function.

const providesTags = (result: ReportPinsResponse | undefined) => {
  if (result && result.items) {
    const { items } = result;
    return [...items.map(({ id }) => ({ type: CACHE_TAGS.Samples, id }))];
  }

  return [CACHE_TAGS.Samples];
};

And then your query mutation will look like:

deleteSample: builder.mutation<void, number>({
    query: (id) => ({
      url: `lithology/delete-sample/${id}`,
      method: 'DELETE',
    }),
    invalidatesTags: (_, __, id) => [{ type: CACHE_TAGS.Samples, id }],
    }),
enum CACHE_TAGS {
  Samples = 'Samples',
}
Larrup answered 17/8, 2023 at 18:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.