Pagination does not work in Apollo React Native

28 views Asked by At

My problem is that pagination for some reason does not work, most likely due to the fact that existing in this file = undefined

import { FieldPolicy } from "@apollo/client/cache/inmemory/policies";
import unionBy from "lodash.unionby";
type KeyArgs = FieldPolicy<string>["keyArgs"];

export const cursorPagination = (
  keyArgs: KeyArgs = ["afterCursor"],
  unionByField = "__ref"
): FieldPolicy => ({
  keyArgs,
  merge(existing, incoming, { args }) {
    const incomingResult = incoming ? incoming.data : [];
    console.log("Incoming", incomingResult);
    const existingResult = existing ? existing.data : [];
    console.log("Existing", existingResult);
    const hasNextCursor = Boolean(args?.pagination?.afterCursor);
    if (hasNextCursor) {
      const resultPagination = unionBy(
        existingResult,
        incomingResult,
        unionByField
      );
      return {
        ...incoming,
        results: resultPagination,
      };
    }
    return incoming;
  },
});

Trying to understand why this is happening, I returned to my request, which is done as follows

export const usePaginationPosts = () => {
  const [getPaginatedPosts, { data, fetchMore }] = usepostsLazyQuery({
    fetchPolicy: "cache-and-network",
  });

  const [afterCursor, setAfterCursor] =
    (useState < string) | null | (undefined > null);
  const [isLoading, setIsLoading] = useState(false);

  const getPosts = useCallback(async () => {
    setIsLoading(true);
    try {
      const response = await getPaginatedPosts({
        variables: {
          input: { limit: 10, afterCursor: null, type: PostFilterType.New },
        },
      });
      setAfterCursor(response.data?.posts.pageInfo?.afterCursor);
      console.log(
        "response.data?.posts.pageInfo?.afterCursor",
        response.data?.posts.pageInfo?.afterCursor
      );
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    getPosts();
  }, [getPosts]);

  const getMorePosts = useCallback(async () => {
    if (afterCursor) {
      const response = await fetchMore({
        variables: {
          input: { limit: 10, afterCursor, type: PostFilterType.New },
        },
      });
      setAfterCursor(response.data?.posts.pageInfo?.afterCursor);
    }
    console.log(afterCursor);
  }, []);

  return { isLoading, getPosts, getMorePosts, data };
};

My theory is that the problem is in afterCursor Just in case, here is my cache option:

export const cacheOption: InMemoryCacheConfig = {
  typePolicies: {
    Query: {
      fields: {
        posts: defaultCursorPagination,
        userMe: defaultCursorPagination,
      },
    },
  },
};

also query the request:

    query posts($input: FindPostsRequest!) {
      posts(input: $input) {
        data {
          author {
            firstName
            lastName
            avatarUrl
          }
          createdAt
          description
          id
          isLiked
          likesCount
          mediaUrl
          title
        }
        pageInfo {
          afterCursor
          count
          perPage
        }
      }
    }

I will be grateful for any help

1

There are 1 answers

0
phry On

I think you're using keyArgs "the wrong way round" here.

The point of keyArgs is to say "if this argument is different, the underlying data does not belong together".

So the way you use it, each different afterCursor will be in a different cache entry and things will never merge together.

You would instead put something like filters in keyArgs, to prevent that listings with different filters would not end up in the same cache entry.