Juan De la Cruz
Juan De la Cruz

Reputation: 465

RTK Query query not refetching after mutation

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).

Upvotes: 7

Views: 10417

Answers (3)

Brogrammer
Brogrammer

Reputation: 472

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',
}

Upvotes: 0

FooBar
FooBar

Reputation: 6128

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,
    ],
});

Upvotes: 2

phry
phry

Reputation: 44136

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 :)

Upvotes: 2

Related Questions