miketromba / drizzle-pagination

Easily paginate your Drizzle ORM queries
MIT License
52 stars 3 forks source link

Inconsistent Response #3

Open rasel-stacklearner opened 6 months ago

rasel-stacklearner commented 6 months ago

in this code when I click on load more button it gives me 20 images. but the second time it does not give me any image.

note: there are 26 images in my database

TRPC Procedure :


export const getImages = protectedProcedure
  .input(
    z.object({
      cursor: z.string().nullish(),
      limit: z.number().default(20),
    }),
  )
  .query(async ({ input, ctx }) => {
    try {
      const { db } = ctx;
      const { cursor, limit } = input;

      const images = await db.query.ImageTable.findMany(
        withCursorPagination({
          limit,
          cursors: [
            [
              ImageTable.createdAt,
              "desc",
              cursor ? new Date(cursor) : undefined,
            ],
          ],
        }),
      );

      const nextCursor = images.length
        ? images[images.length - 1]?.createdAt?.toISOString()
        : null;
      return {
        images,
        nextCursor: nextCursor,
      };
    } catch (error) {
      throw customError(error);
    }
  });

Frontend Code =>

import { useEffect, useMemo, useRef } from "react";
import Image from "next/image";
import ImageSkeleton from "@/components/shared/skeleton/ImageSkeleton";
import { api } from "@/utils/trpc/client";
import { Loader } from "lucide-react";
import { Button } from "@ui/components/ui/button";

type ImageType = {
  id: string;
  smallUrl: string | null;
  mediumUrl: string | null;
  largeUrl: string | null;
};

const ImageGallery = () => {
  const lastImageRef = useRef<HTMLDivElement | null>(null);

  const { data, isLoading, fetchNextPage, isFetchingNextPage } =
    api.media.resources.useInfiniteQuery(
      {
        // limit: 5,
      },
      {
        getNextPageParam: (lastPage) => lastPage.nextCursor,
      },
    );

  const images = useMemo(
    () => data?.pages.flatMap((page) => page.images ?? []),
    [data],
  );

  return (
    <>
      {/* Skeleton */}
      {isLoading && (
        <div className="flex flex-wrap gap-2 ">
          {Array.from({ length: 20 }).map((_, index) => (
            <ImageSkeleton key={index} />
          ))}
        </div>
      )}

      <div className="mt-1 flex max-h-[250px] flex-wrap gap-2 overflow-y-auto">
        {images &&
          images?.length > 0 &&
          images?.map((image, index) => {
            return (
              <div
                key={image.id}
                className={`relative h-28 w-28`}

              >
                <Image
                  src={image.smallUrl!}
                  alt="image"
                  className="cursor-pointer rounded border-4 border-slate-900 object-cover"
                  fill
                  sizes="120px"
                />
              </div>
            );
          })}
      </div>

      <div className="flex w-full justify-center">
        <Loader
          className={`animate-spin  ${isFetchingNextPage ? "visible" : "invisible"}`}
        />
      </div>
      <Button onClick={async () => {

        fetchNextPage()
      }}>Load More</Button>
    </>
  );
};

export default ImageGallery;
miketromba commented 3 months ago

@rasel-stacklearner My first thought: Are all of the createdAt dates guaranteed to be unique? If not, you should add a secondary, unique, sequential cursor in order to guarantee a stable sort (e.g. ID).

See: https://github.com/miketromba/drizzle-pagination?tab=readme-ov-file#with-two-cursors-one-non-unique-sequential-cursor-with-a-unique-cursor-as-a-fallback

I don't have time to analyze your code in detail, but the next thought would be to double-check that you are using the proper cursor value (and not accidentally supplying the wrong value) to the withCursorPagination function.