reactjstypescriptnext.js

Trying to create a reusable shadcn table, that takes pagination from a laravel api, instead of client side pagination


I am trying to create a reusable shadcn table which i can use to render data gotten from an API. The API handles the pagination and sends back something like this with the response data:

    "next_page_url": "REDACTED/payments?page=2",
    "path": "REDACTED/payments",
    "per_page": 15,
    "prev_page_url": null,
    "to": 15,
    "total": 31

I tried using the Shadcn Data Table but ended up with a table with broken/not functioning pagination due to the length of data being passed to it.

 <div className='flex flex-wrap items-center gap-4'>
        <DataTableSearch
          searchKey='name'
          searchQuery={searchQuery}
          setSearchQuery={setSearchQuery}
          setPage={setPage}
        />
        <DataTableFilterBox
          filterKey='role'
          title='Role'
          options={ROLE_OPTIONS}
          setFilterValue={setRoleFilter}
          filterValue={roleFilter}
        />
        <DataTableResetFilter
          isFilterActive={isAnyFilterActive}
          onReset={resetFilters}
        />
      </div>
      <DataTable columns={columns} data={data} totalItems={totalData} />
</div>

Solution

  • Shadcn Datatable works for client-side pagination for smaller data chunks, I suggest you use the shadcn regular table, and a pagination component to manage the page count and next and prev

    See a basic example in Nextjs

    "use client";
    
    import { Button } from "@/components/ui/button";
    import { useRouter, useSearchParams } from "next/navigation";
    
    interface PaginationProps {
      currentPage: number;
      lastPage: number;
    }
    
    export function Pagination({ currentPage, lastPage }: PaginationProps) {
      const router = useRouter();
      const searchParams = useSearchParams();
    
      const handlePageChange = (page: number) => {
        const params = new URLSearchParams(searchParams.toString());
        params.set("page", page.toString());
        router.push(`?${params.toString()}`);
      };
    
      return (
        <div className="flex items-center justify-end space-x-2 py-4">
          <div className="text-sm text-muted-foreground">
            Page {currentPage} of {lastPage}
          </div>
          <div className="space-x-2">
            <Button
              variant="outline"
              size="sm"
              disabled={currentPage === 1}
              onClick={() => handlePageChange(currentPage - 1)}
            >
              Previous
            </Button>
            <Button
              variant="outline"
              size="sm"
              disabled={currentPage === lastPage}
              onClick={() => handlePageChange(currentPage + 1)}
            >
              Next
            </Button>
          </div>
        </div>
      );
    }

    This allows you to change the page in the URL and in the parent component you can use this to update the page and fetch the new page data.

    I hope this helps!