Easiest way to Create React tables (NEXTJS)
Tags: react, nextjs, javascript, webdev
Published: 2023-05-27 14:15:29

You must have encounter the situations where you have to build a react table, and honestly they are some real problem. So we can use some component library to make them easy, like we can use some component libraries like material UI but the problem with tables in material UI is that you have to ship a very large amount of javascript to browser as it should be a client side component. 
But now this problem is solved with a new component DATA TABLE by [shadcn UI](https://ui.shadcn.com/).

![Data table preview by shadcn UI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bo6o6xa64zdr7jg74lbm.png)

You can filter and sort the email, can check all the fields, can enable and disable any sort of columns, and above all this have built-in pagination

So let's build it
first of all install the npm package by running command
`npm install @tanstack/react-table
`
and here is the folder structure:

### **Folder structure**
 app
└── payments
    ├── columns.tsx
    ├── data-table.tsx
    └── page.tsx


**The column component** is where we declare what data is shown for each column for example the email and amount  
 
and to display all the information we will use the **DataTable component** which will handle all the data

### Code
read the comments within the code:

#### Column.tsx:
  

```
"use client"

import { ColumnDef } from "@tanstack/react-table"

// This type is used to define the shape of our data. e.g we want our id to be string and status none other than these four options
export type Payment = { 
  id: string
  amount: number
  status: "pending" | "processing" | "success" | "failed"
  email: string
}

export const columns: ColumnDef<Payment>[] = [
//we can set normal fields like this
  {
    accessorKey: "status",
    header: "Status",
  },
  {
    accessorKey: "email",
    header: "Email",
  },
//
  {
    accessorKey: "amount",
    header: () => <div className="text-right">Amount</div>,
    cell: ({ row }) => {
      const amount = parseFloat(row.getValue("amount"))
      const formatted = new Intl.NumberFormat("en-US", {
        style: "currency",
        currency: "USD",
      }).format(amount)
 
//we can format the amount in any currency without any use of external package

      return <div className="text-right font-medium">{formatted}</div>  
    },
  },
]

```

#### DataTable.tsx

```
"use client"
//we have to import a lot of things and here are they
import {
  ColumnDef,
  flexRender,
  getCoreRowModel,
  useReactTable,
} from "@tanstack/react-table"

import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table"

//now we are expecting 2 props: columns and the data(that we are expecting from the page component)
interface DataTableProps<TData, TValue> {
  columns: ColumnDef<TData, TValue>[]
  data: TData[]
}

export function DataTable<TData, TValue>({
  columns,
  data,
}: DataTableProps<TData, TValue>) {
// and now we will use this useReactTable hook
  const table = useReactTable({
    data,
    columns,
    getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel()

// and yes adding pagination can be done with just this above one line 

  })

  return (
    <div className="rounded-md border">
      <Table>
        <TableHeader>
          {table.getHeaderGroups().map((headerGroup) => (
            <TableRow key={headerGroup.id}>
              {headerGroup.headers.map((header) => {
                return (
                  <TableHead key={header.id}>
                    {header.isPlaceholder
                      ? null
                      : flexRender(
                          header.column.columnDef.header,
                          header.getContext()
                        )}
                  </TableHead>
                )
              })}
            </TableRow>
          ))}
        </TableHeader>
        <TableBody>
          {table.getRowModel().rows?.length ? (
            table.getRowModel().rows.map((row) => (
              <TableRow
                key={row.id}
                data-state={row.getIsSelected() && "selected"}
              >
                {row.getVisibleCells().map((cell) => (
                  <TableCell key={cell.id}>
                    {flexRender(cell.column.columnDef.cell, cell.getContext())}
                  </TableCell>
                ))}
              </TableRow>
            ))
          ) : (
            <TableRow>
              <TableCell colSpan={columns.length} className="h-24 text-center">
                No results.
              </TableCell>
            </TableRow>
          )}
        </TableBody>
      </Table>

//now to use the pagination we will use the buttons

<button onClick={()=>table.previouspage()}>Previous page</button>
<button onClick={()=>table.nextpage()}>Next Page</button>
    </div>
  )
}

```

and here is out page.tsx folder:

```
import { Payment, columns } from "./columns"
import { DataTable } from "./data-table"

async function getData(): Promise<Payment[]> {
// and this Payment[] is imported from .columns which will again controll the type of that data that is passed from the server component to the client component
  
// Fetch data from your API here.

  return [
    {
      id: "728ed52f",
      amount: 100,
      status: "pending",
      email: "m@example.com",
    },
    // ...
  ]
}

export default async function DemoPage() {
  const data = await getData()

  return (
    <div className="container mx-auto py-10">
      <DataTable columns={columns} data={data} />
    </div>
  )
}

```

and that's all, don't forget to check the [official documentation](https://ui.shadcn.com/docs/components/data-table) of the component 

Follow me on [Twitter](https://twitter.com/DEVOSORUS_J9A) and [Instagram](https://www.instagram.com/devosorus/)
for more such content 

- DEVOSORUS