0

I'm using RTK query and I want to overwrite the state with the result from my transform request. I get my overview of a todos array by calling the getTodosOverview Query. After that I call a updateTodos query and this gives me back a new array with todos. I want to overwrite the original array with these results. I'm using the function updateQueryData but it doesnt seem to work. What am I missing here?

export const todosApi = createApi({
    reducerPath: 'todosApi',
    baseQuery: fetchBaseQuery({ baseUrl: 'api/todos' }),
    endpoints: (builder) => ({
      getToDosOverview: builder.query<Array<ToDos>, string>({
        query: () => `getOverview`,
        transformResponse: (rawResult: { data: Array<ToDos> }) => rawResult.data,
        keepUnusedDataFor: 0,
      }),
      updateTodos: builder.mutation<Array<ToDos>, string>({
        query: (fileId) => ({
          url: `updateTodos?fileId=${fileId}`,
          method: 'POST',
        }),
        transformResponse: (rawResult: { data: Array<ToDos> }) => rawResult.data,
        async onQueryStarted(uniqueIdentifier, { dispatch, queryFulfilled }) {
          const { data }= await queryFulfilled;
          // Update state with new data from response
          const patchResult = dispatch(
            todosApi.util.updateQueryData(
              'getToDosOverview',
              uniqueIdentifier,
              () => {
                return data;
              }
            )
          );
        },
      }),
    }),
  });
Jim Peeters
  • 2,573
  • 9
  • 31
  • 53

1 Answers1

2

Well, you're not returning anything new.

          const patchResult = dispatch(
            todosApi.util.updateQueryData(
              'getToDosOverview',
              uniqueIdentifier,
              // here you are getting the old state as a variable called `ToDos`
              (ToDos: Array<ToDos>) => {
                // and here you return that old state without any change
                return ToDos;
              }
            )
          );

Also, you are doing that way before you have even received a response.

The response will be available after the line

await queryFulfilled;

so you probably want to do something like

const { data } = await queryFulfilled

and then use data as the new value.

Generally, it seems like you are copy-pasting from the "optimistic updates" example. Please look at the example of pessimistic updates instead.

Also, with your code you are using the wrong argument if you want to update useGetToDosOverviewQuery(). You are updating useGetToDosOverviewQuery(uniqueIdentifier) here.

You should probably call

todosApi.util.updateQueryData('getToDosOverview', undefined, ...)
phry
  • 35,762
  • 5
  • 67
  • 81
  • i have updated my code in the description and also I also done the same update in my application but still it doesnt get overwritten – Jim Peeters Feb 18 '22 at 08:27
  • You are updating `useGetToDosOverviewQuery(uniqueIdentifier)` here, not `useGetToDosOverviewQuery()` with your code. Do you maybe want to `todosApi.util.updateQueryData('getToDosOverview', undefined, ...)` ? – phry Feb 18 '22 at 08:44
  • Hey thanks! that indeed worked, when matching the second parameter with the arg from the getTodosOverview it worked! if u post it as an answer i can complete it. so i adapted: "getToDosOverview: builder.query, string>({" to "getToDosOverview: builder.query, undefined>({" and then "todosApi.util.updateQueryData( 'getToDosOverview',uniqueIdentifier to todosApi.util.updateQueryData( 'getToDosOverview', undefined – Jim Peeters Feb 18 '22 at 10:13
  • I edited it at the end of my answer. – phry Feb 18 '22 at 11:09
  • How to achieve this if you have dynamic arguments in getToDosOverview? – Gaccho Jun 02 '22 at 12:25
  • @Gaccho you will have to call that with the exact arguments used for the query instead of `undefined` - for every cache entry you want to update. – phry Jun 02 '22 at 13:09
  • @phry Thanks. And if you want to update only the latest cache entry? Should save those dynamic arguments in a state to access them in `updateQueryData`? – Gaccho Jun 03 '22 at 10:56
  • @Gaccho For RTK-Q itself, there is no concept of a "latest" cache entry - assume you have three components all rendered at the same time calling useSomethingQuery with different arguments - there is not really a "last" one, the order in which they render can be completely random. So yes, you would have to save those arguments that are of interest for you in the store. – phry Jun 03 '22 at 11:12