1

I am using RTK query in my react-native app, and I have a List of Home Posts and List of user posts and each has a skip param that is increment onEndReached

I have a mutation fn deletePost that when trigger I invalidate both Lists.

My problem is the API are called with the current skip set like it might be like 30, so the posts list will not be updated properly.

How Can I resolve this ? Is there a way to do it without the need to call the APIs to just delete it from the cache ?

Here is my implementation:

export const postAPI = createApi({
  reducerPath: 'postAPI',
  baseQuery: fetchBaseQuery({
    baseUrl: `${DOMAIN}/api`,
    prepareHeaders: (headers, { getState }) => {
      const token = getState().auth.authToken;
      const countryCode = getState().auth?.location?.countryCode || 'QA';
      if (token) {
        headers.set('authorization', `Bearer ${token}`);
      }
      if (countryCode) {
        headers.set('X-Country-Code', countryCode);
      }
      headers.set('Accept-Language', i18n.language);
      return headers;
    },
  }),
  tagTypes: ['Post'],
  endpoints: (build) => ({
    getPosts: build.query({
      query: (body) => ({
        url: 'post/filter',
        method: 'POST',
        body: body,
      }),
      merge: (currentCache, newItems) => {
        currentCache.push(...newItems);
      },
      transformResponse: (res) => {
        return res.data || [];
      },
      providesTags: (result) =>
        result
          ? [
              ...result.map(({ _id }) => ({ type: 'Post', id: _id })),
              { type: 'Post', id: 'LIST' },
            ]
          : [{ type: 'Post', id: 'LIST' }],
      serializeQueryArgs: ({ endpointName }) => {
        return endpointName;
      },
      forceRefetch({ currentArg, previousArg }) {
        return JSON.stringify(currentArg) !== JSON.stringify(previousArg);
      },
    }),
    getMyPosts: build.query({
      query: ({ params, cond }) => ({
        url: `post/my-ads/${cond}`,
        method: 'GET',
        params,
      }),
      transformResponse: (response) => {
        return response?.data;
      },
      serializeQueryArgs: ({ endpointName, queryArgs }) => {
        return `${endpointName}_${queryArgs.cond}`;
      },
      forceRefetch: ({ currentArg, previousArg }) => {
        return currentArg?.params?.skip !== previousArg?.params?.skip;
      },
      merge: (currentState, incomingState, { arg }) => {
        if (arg?.params?.skip !== 0) {
          return [...currentState, ...incomingState];
        }
        return incomingState;
      },
      providesTags: (result) =>
        result
          ? [
              ...result.map(({ _id }) => ({ type: 'Post', id: _id })),
              { type: 'Post', id: 'My' },
            ]
          : [{ type: 'Post', id: 'My' }],
    }),
    getFilteredPosts: build.query({
      query: (body) => ({
        url: 'post/filter',
        method: 'POST',
        body,
      }),
      transformResponse: (res) => {
        return res.data || [];
      },
      merge: (currentState, incomingState, { arg }) => {
        if (arg?.skip !== 0) {
          return [...currentState, ...incomingState];
        }
        return incomingState;
      },
      providesTags: (result) =>
        result
          ? [
              ...result.map(({ _id }) => ({ type: 'Post', id: _id })),
              { type: 'Post', id: 'Explore' },
            ]
          : [{ type: 'Post', id: 'Explore' }],
      serializeQueryArgs: ({ endpointName, queryArgs }) => {
        const { skip, limit, ...args } = queryArgs;
        return `${endpointName}_${JSON.stringify(args)}`;
      },
      forceRefetch: ({ currentArg, previousArg }) => {
        return JSON.stringify(currentArg) !== JSON.stringify(previousArg);
      },
    }),

    deletePost: build.mutation({
      query: (postId) => ({
        url: `post/delete/${postId}`,
        method: 'DELETE',
        params: { vehicleCategory: 'all' },
      }),
      transformResponse: (response) => response.data,
      invalidatesTags: () => [
        { type: 'Post', id: 'LIST' },
        { type: 'Post', id: 'My' },
      ],
    }),
});

and here is a sample for my Home Posts List:

const [skip, setSkip] = useState(0);
  const {
    data = [],
    isFetching: isLoading,
    refetch,
  } = useGetPostsQuery({
    countryCode: currentCountryCode,
    skip,
    limit: LIMIT,
  });

  <AdsList
    ads={data}
    loading={isLoading}
    Header={HomeListHeader}
    HeaderStyle={styles.header}
    onRefresh={() => {
      dispatch(setHomeSkip(0));
      refetch({ skip: 0, limit: LIMIT, countryCode: currentCountryCode });
    }}
    handleMoreAds={() => {
      if (!isLoading) {
        setSkip((prev) => prev + LIMIT);
      }
    }}
    onPressThreeDot={onPressThreeDot}
    isRefreshing={isLoading && skip === 0}
    HeaderLoadingComponent={HomeListHeaderLoading}
  />
warCommander
  • 392
  • 4
  • 19

0 Answers0