Frequently Asked Questions

React Table & Technical Implementation

What is React Table and how does it work with Hygraph?

React Table is a free, open-source, headless library (part of TanStack Table) for building tables in React applications. It provides hooks for sorting, filtering, and pagination, allowing developers to fully customize the UI. With Hygraph, you can fetch data via its GraphQL API and display it in tables using React Table. This integration enables dynamic, flexible data presentation in your React projects. Source

What are the main features of React Table?

React Table offers a lightweight (5kb - 14kb+), headless design, full customizability (JSX, templates, state, styles, callbacks), TypeScript support, and does not influence data calls. It supports filtering, sorting, pagination, and more, making it ideal for building complex tables in React. Source

How do you fetch data from Hygraph for use in React Table?

You can fetch data from Hygraph using its GraphQL API and the graphql-request library. After installing the necessary packages, you define your data types and API requests, then use React hooks (useState, useEffect) to retrieve and store the data for use in your table component. Source

How do you define columns in React Table for Hygraph data?

Columns are defined as objects specifying headers and accessor keys that map to your data fields. You can customize column rendering using properties like cell for formatting and accessorFn for combining fields. This allows you to tailor the table display to your specific data structure from Hygraph. Source

What table operations are supported by React Table?

React Table supports filtering, sorting, and pagination. These operations can be implemented using state variables and React Table's API hooks, allowing for both client-side and server-side data manipulation. Source

How can you make React Table reusable for different data types?

To make React Table reusable, decouple the data and column definitions from the table component. Pass them as props using TypeScript generics, allowing the table to display any type of data (e.g., employees, products, orders) without being tied to a specific context. Source

What UI frameworks can be used with React Table?

React Table is headless and does not render markup or styles, so you can use any UI framework, such as Chakra UI, Material-UI, or Ant Design, to style your tables. Source

How do you implement sorting in React Table?

Sorting is implemented by creating a state variable for sorting, passing it to the table instance, and using the getSortedRowModel hook. You can add click events to column headers to toggle sorting between ascending, descending, and none. Source

How do you implement filtering in React Table?

Filtering is achieved by setting up a state variable for the filter input, passing it to the table instance, and using the getFilteredRowModel hook. This enables dynamic filtering of table data based on user input. Source

How do you implement pagination in React Table?

Pagination is implemented by importing getPaginationRowModel and passing it to the table instance. You can then use utility functions like firstPage, previousPage, nextPage, and lastPage to navigate through table pages. Source

What are the benefits of using React Table with Hygraph?

Using React Table with Hygraph allows you to build highly customizable, performant tables that can display dynamic data fetched via GraphQL. This combination supports advanced features like sorting, filtering, and pagination, and enables scalable content management for modern web applications. Source

How does React Table enhance user interaction?

React Table enhances user interaction by providing interactive headers for sorting and pagination controls for navigating through data, resulting in a more dynamic and user-friendly experience. Source

Why should you consider using React Table?

React Table is highly customizable, lightweight, fast, and has strong community support. It offers an extensive API for all table-related operations and proper TypeScript support, making it a preferred choice for tech companies and developers. Source

How can I efficiently use the react-table library to create tables in a React application?

You can efficiently use the react-table library by following the step-by-step guide available here, which covers data fetching, column definition, and implementing sorting, filtering, and pagination.

What is the purpose of the React Table example in the blog?

The React Table example demonstrates how to implement a table with features like pagination, sorting, and filtering using React and the TanStack library, specifically with data fetched from Hygraph. Source

How can React Table be used to build a table in a React application?

React Table provides hooks such as useReactTable to instantiate a table and access methods for creating and managing table data. You define columns and data, memoize columns with useMemo, and create table markup using HTML tags. UI frameworks like Chakra UI can be used for styling. Source

What is the React Table library used for?

The React Table library is used to display data in a tabular format, providing utilities like filtering, pagination, and sorting for enhanced data management in React applications. Source

How do I use the react-table library?

To use the react-table library, follow the guide on the Hygraph blog, which covers installation, data fetching, column definition, and implementing table operations like sorting, filtering, and pagination. Source

How to use the react-table library?

Learn how to efficiently use the react-table library to create tables in React applications by following the tutorials and examples provided on the Hygraph blog. Source

Where can I find more resources about React Table and Hygraph?

You can find more resources, guides, and tutorials on the Hygraph blog and documentation pages. Source

Features & Capabilities

What features does Hygraph offer for content management?

Hygraph offers a GraphQL-native Headless CMS with features such as Smart Edge Cache for fast content delivery, content federation for integrating multiple data sources, granular permissions, SSO integrations, audit logs, encryption, regular backups, and enterprise-grade compliance. Source

Does Hygraph support integration with third-party systems?

Yes, Hygraph supports extensive integration capabilities, including eCommerce platforms, localization tools, and digital asset management systems, enabling businesses to connect their tech stacks seamlessly. Source

What is Smart Edge Cache in Hygraph?

Smart Edge Cache is a feature in Hygraph that ensures enhanced performance and faster content delivery, making it ideal for businesses with high traffic and global audiences. Source

What security and compliance certifications does Hygraph have?

Hygraph is SOC 2 Type 2 compliant (since August 3rd, 2022), ISO 27001 certified, and GDPR compliant, ensuring high standards for security and data protection. Source

How does Hygraph ensure data security?

Hygraph ensures data security through granular permissions, SSO integrations, audit logs, encryption at rest and in transit, regular backups, and a transparent process for reporting security issues. Source

What performance improvements has Hygraph made to its endpoints?

Hygraph has made significant improvements to its high-performance endpoints, ensuring reliability and speed for content delivery. Details are available in their blog post on endpoint improvements. Source

How does Hygraph measure and optimize GraphQL API performance?

Hygraph measures the performance of its GraphQL API and provides practical advice for developers to optimize API usage, ensuring best possible performance for applications. Source

Use Cases & Benefits

Who can benefit from using Hygraph?

Hygraph is ideal for developers, product managers, and marketing teams in industries such as ecommerce, automotive, technology, food and beverage, and manufacturing. It is especially suited for organizations modernizing legacy tech stacks and global enterprises requiring localization and content federation. Source

What problems does Hygraph solve for businesses?

Hygraph solves operational inefficiencies (reducing developer dependency, modernizing legacy tech stacks), financial challenges (lowering costs, accelerating speed-to-market), and technical issues (simplifying schema evolution, improving integration, optimizing performance, and enhancing localization and asset management). Source

What are some customer success stories with Hygraph?

Komax achieved a 3X faster time-to-market, Autoweb saw a 20% increase in website monetization, Samsung improved customer engagement by 15%, and Stobag increased online revenue share from 15% to 70% after transitioning to Hygraph. Source

How easy is it to implement Hygraph?

Implementation time varies by project. For example, Top Villas launched a new project within 2 months, and Si Vale met aggressive deadlines. Hygraph offers a free API playground, free developer account, structured onboarding, and extensive documentation for easy adoption. Source

What feedback have customers given about Hygraph's ease of use?

Customers praise Hygraph's intuitive editor UI, accessibility for non-technical users, and custom app integration. Hygraph was recognized for "Best Usability" in Summer 2023. Source

What KPIs and metrics are associated with Hygraph's solutions?

Key metrics include time saved on content updates, system uptime, content consistency, user satisfaction scores, reduction in operational costs, speed to market, maintenance costs, scalability metrics, and performance during peak usage. Source

How does Hygraph differentiate itself from other CMS platforms?

Hygraph stands out as the first GraphQL-native Headless CMS, offering content federation, user-friendly tools, enterprise-grade features, and unparalleled flexibility and scalability. Its approach differs from competitors like Sanity, Prismic, and Contentful by focusing on composability and integration. Source

What is the primary purpose of Hygraph?

Hygraph empowers businesses to build, manage, and deliver exceptional digital experiences at scale by eliminating traditional CMS pain points and providing flexibility, scalability, and efficiency for modern workflows. Source

What is Hygraph's vision and mission?

Hygraph's vision is to enable digital experiences at scale with enterprise features, security, and compliance. Its mission is rooted in trust, collaboration, ownership, customer focus, continuous learning, transparency, and action-first values. Source

How does Hygraph handle value objections?

Hygraph addresses value objections by understanding customer needs, highlighting unique features (API-first, headless, GraphQL), demonstrating ROI (cost reduction, speed to market, scalability), and sharing success stories like Samsung's engagement improvement. Source

What pain points do Hygraph customers commonly express?

Customers often mention operational inefficiencies (developer dependency, legacy tech stacks), financial challenges (high costs, slow speed-to-market), and technical issues (schema evolution, integration difficulties, cache problems, localization, asset management). Source

How does Hygraph solve each of these pain points?

Hygraph solves operational inefficiencies with a user-friendly interface and GraphQL-native architecture, financial challenges with cost efficiency and integration capabilities, and technical issues with robust APIs, Smart Edge Cache, and enhanced localization and asset management. Source

Introducing Click to Edit

React Table: A Complete Guide

How to efficiently use the react-table library to create tables in our React application.
Aagam Vadecha

Last updated by Aagam 

Sep 08, 2024

Originally written by Joel

React Table: A Complete Guide

A table is an arrangement that organizes any information into rows and columns—it stores and displays data in a structured and clear format that everyone can understand. For example, when you want to display dashboard statistics, a list of details such as staff details, products, students, and lots more.

Implementing tables in React can get cumbersome and technical, especially when you need to perform basic table functionalities like sorting, filtering, pagination, and lots more.

#What is React Table?

Tanstack table is a free open-source headless library with around 25K stars on GitHub. It allows you to build tables and has individual libraries to support different frameworks like React, Vue, Angular, Solid, etc.

Tanstack React Table or React Table library is part of the tanstack table that allows us to build tables in React applications. It gives you an API to build tables and do different operations on them, it follows a headless UI approach and allows you to fully build your custom UI. It is also very flexible to use.

React table uses hooks to help build tables, giving you complete control over how you want the UI to appear and function (Headless UI). These hooks are lightweight, fast, fully customizable, and flexible but do not render any markup or styles for you. React Table is used by many well-known tech companies due to its flexibility and easy-to-implement features. These features, such as sorting, pagination, and filtering, are implemented with hooks.

#React table features

React Table has some fantastic features that make it easy to build tables. These features include:

  • It is lightweight, about 5kb - 14kb+.
  • Headless design, manage state and hooks for all functionalities, use your own UI
  • It is fully customizable (JSX, templates, state, styles, callbacks).
  • TypeScript support.
  • Does not influence data calls (it does not perform data calls; it just uses passed-in data).
  • Support for table functionalities like filtering, sorting, pagination, and many more.

#Should you use React Table?

You can check these points to see if you should be using the React Table library

The current UI framework does not provide a Table component

If your current UI framework does not provide a table component and you need to add a table, then you can consider React Table to manage all tables in your application. UI Frameworks like Material-UI or AntD would already have a Table component, in those cases maybe checking if those components fulfill your requirements would make more sense.

Headless Solution

If you want full control over the table's look and feel without being tied to any specific UI or styling framework. React Table’s headless design seamlessly integrates CSS and different UI libraries. Again, if your UI library already has a Table component that works for your use cases, it does not make sense to add extra overhead with an additional library.

Other Considerations

  • It is highly customizable and provides an extensive API for all table-related operations.
  • It has strong community support.
  • It is lightweight, fast, and comes with proper TypeScript support.
  • It has an intermediate learning curve and will need some time for API exploration and using various features.

#Building a Table

In this article, we will fetch some data from Hygraph via GraphQL, and then display that data in a table using the @tanstack/react-table library. Also, we will implement client-side sorting, filtering, and pagination, and finally, we will see how to extend our table component to display any kind of data. In our Hygraph project, we have created a model and populated it with some mock employee data. Hygraph is a headless CMS that enables teams to distribute content to any channel. If this is your first time learning about Hygraph, establish a free-forever developer account.

Base setup

In a situation where you have successfully added all your data to hygraph, or you have your content API ready, we can now fetch these data into our application and store it in a state.

To fetch our data from Hygraph, we use GraphQL using the graphql-request library. We can install this library using the command below in our project directory. Also, we will be using TanStack table’s React library to build our table. We will need to install this library as well.

npm i graphql-request
npm i @tanstack/react-table

Getting data from Hygraph

Once the above installation is done, we can navigate to a fresh component to create our table. We will use useState() to store our data and the useEffect() hook to fetch our data from Hygraph.

Let us declare types for our data first

types.ts

export interface IEmployee {
id: number,
firstName: string;
lastName: string;
email: string;
department: string;
dateJoined: string;
}

Create a file to store our API requests.

api.ts

import request from "graphql-request";
import { HYGRAPH_URL } from "./utils/constants";
export const getTableData = async () => {
const response = await request(
HYGRAPH_URL,
`{
employees (first:50) {
id_number
firstName
lastName
email
department
dateJoined
}
}`
);
return response;
};

Use the API request in our component to fetch the data

ReactTable.tsx

import { getTableData } from "../../api.ts";
import { useState, useEffect } from "react";
import { IEmployee } from "../../utils/types.ts";
export const ReactTable = () => {
const [data, setData] = useState<IEmployee[]>([]);
useEffect(() => {
const fetchData = async () => {
const { employees } = await getTableData();
setData(employees);
};
fetchData();
}, []);
return <div>...</div>;
};

Column definition

When using React tables, data and columns are the two significant pieces of information needed. The information we will pass into the rows is known as the data, and the objects used to define the table columns are called the columns (headers, rows, how we will show the row, etc.). We will create columns in a separate file and then import them into our component.

columns.ts

import { ColumnDef } from "@tanstack/react-table";
import { IEmployee } from "../../utils/types";
export const COLUMNS: ColumnDef<IEmployee>[] = [
{
header: "ID",
accessorKey: "id_number",
},
{
header: "First Name",
accessorKey: "firstName",
},
{
header: "Last Name",
accessorKey: "lastName",
},
{
header: "Email",
accessorKey: "email",
},
{
header: "Department",
accessorKey: "department",
},
{
header: "Date Joined",
accessorKey: "dateJoined",
},
];

The columns array consists of objects representing single columns in our table. Currently, we have specified the configuration of these objects with two items:

  • header: This is the column's header, which will be displayed at the top of each column.
  • accessorKey: this is the key from our data that will be used to assign value to a column.

There can be more configuration added to this column object, for example, this is how one row of our data coming from Hygraph looks like:

{
id: 1,
firstName: "Tandi",
lastName: "Withey",
email: "twithey0@arizona.edu",
department: "Marketing",
dateJoined: "2014-10-23T07:29:35Z",
}

The dateJoined column value like this 2014-10-23T07:29:35Z will look bad and unreadable in the table with all the hour, minute, and second data. We can use the cell property to display the data however we want as shown below:

...
{
header: "Date Joined",
accessorKey: "dateJoined",
cell: (info) => {
const value = (info.getValue() as string).substring(0,10)
return value
}
}
...

Next, let's say instead of displaying firstName and lastName as two different columns we want to combine data into a single column, we can do it using the accessorFn property as shown below:

...
{
header: "Name",
accessorFn: (row) => `${row.firstName} ${row.lastName}`,
}
...

These are some basic use cases, for custom requirements you can further explore the column definition API in detail here

The Table instance

React table makes use of hooks in its headless approach. The first hook we will use is the useReactTable hook to instantiate our table so we can access all the methods needed to create our table.

The useReactTable hook requires at least columns, data, and getCoreRowModel to be passed to it as an argument. We should also use the useMemo hook to help memoize our columns array to avoid unnecessary re-renders.

ReactTable.tsx

// other imports ...
import { IEmployee } from "../../../utils/types.ts";
import { COLUMNS } from "./columns.ts";
import { getCoreRowModel, useReactTable } from "@tanstack/react-table";
export const ReactTable = () => {
const [data, setData] = useState<IEmployee[]>([]);
// useEffect() to fetch data ...
const columns = useMemo(() => COLUMNS, []);
const table = useReactTable({
columns,
data,
getCoreRowModel: getCoreRowModel(),
});
return <div>...</div>;
};

Markup for the table

From the table instance table above we can get functions like getHeaderGroups, getRowModel, and getFooterGroups, these functions can be used to form our table markup.

Let's destructure directly to access these props:

ReactTable.tsx

...
const { getHeaderGroups, getRowModel, getFooterGroups } = table;
...

For table markup, we can use HTML tags like table, thead,tbody, tfoot, th, tr, and td. We are using Chakra for this example but feel free to use any UI framework of your choice.

ReactTable.tsx

import {
useReactTable,
getCoreRowModel,
flexRender,
} from "@tanstack/react-table";
import {
Table,
TableContainer,
Tbody,
Td,
Tfoot,
Th,
Thead,
Tr,
} from "@chakra-ui/react";
export const ReactTable = () => {
// all existing logic code ...
const { getHeaderGroups, getRowModel, getFooterGroups } = table;
return (
<TableContainer p={8}>
<Heading>React Table Example</Heading>
<Table>
<Thead>
{getHeaderGroups().map((headerGroup) => (
<Tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<Th key={header.id}>
{flexRender(header.column.columnDef.header, header.getContext())}
</Th>
))}
</Tr>
))}
</Thead>
<Tbody>
{getRowModel().rows.map((row) => (
<Tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<Td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</Td>
))}
</Tr>
))}
</Tbody>
<Tfoot>
{getFooterGroups().map((footerGroup) => (
<Tr key={footerGroup.id}>
{footerGroup.headers.map((header) => (
<Th key={header.id}>
{flexRender(header.column.columnDef.footer, header.getContext())}
</Th>
))}
</Tr>
))}
</Tfoot>
</Table>
</TableContainer>
);
};

At this point, when we check our browser, our table will look like this

React Table Basic.PNG

Pretty cool, pat your back if you got till here 😎

#Basic table operations

We can use React Table’s API to perform common table-related operations like filtering, pagination, and sorting. Ideally, for very huge datasets these operations happen on the server side. However, for this article and understanding React Table’s API we will demonstrate how to do basic filtering, pagination, and sorting using the React Table API.

Filtering

For filtering the table data first we will need to set up a state variable and capture the user input for filtering the data

// ... existing code …
const [globalFilter, setGlobalFilter] = useState("");
// ... existing code ...
<Input
value={globalFilter || ""}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder="Search all columns..."
my={4}
/>
// ... existing code ...

We will need to import getFilteredRowModel and pass it in the react table object initialization. Also, we will need to pass our state globalFilter and its function setGlobalFilter while creating the table instance as shown below:

import { getFilteredRowModel } from "@tanstack/react-table";
const table = useReactTable({
// ... existing code ...
state: {
globalFilter,
},
getFilteredRowModel: getFilteredRowModel(),
onGlobalFilterChange: setGlobalFilter,
});

Below is all the combined code that we will need for implementing table filtering.

// ... existing code ...
import {
// ... existing code ...
getFilteredRowModel,
} from "@tanstack/react-table";
export const ReactTable = () => {
// ... existing code ...
const [globalFilter, setGlobalFilter] = useState("");
// ... existing code ...
const table = useReactTable({
columns,
data,
state: {
globalFilter,
},
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onGlobalFilterChange: setGlobalFilter,
});
const { getHeaderGroups, getRowModel, getFooterGroups } = table;
return (
<TableContainer>
<Input
value={globalFilter || ""}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder="Search all columns..."
my={4}
/>
// ... existing code ...
)

Pagination

Similarly, for pagination, we will need to import getPaginationRowModel and pass it in the table instance initialization.

// ... existing code …
import { getPaginationRowModel } from "@tanstack/react-table";
// ... existing code ...
const table = useReactTable({
// ... existing code ...
getPaginationRowModel: getPaginationRowModel(),
});

That’s it, now we can use react table’s API and build some basic pagination functionality like going to the previous page, next page, first page, and last page. First, we need to destructure the required utility functions from the table instance as shown below

const {
// ... existing code ...
firstPage,
previousPage,
lastPage,
nextPage,
getCanNextPage,
getCanPreviousPage,
} = table;

firstPage will allow us to navigate to the first page, lastPage will send the user to the last page of the table, getCanPreviousPage will return a boolean value if the user can go to the previous page, previousPage will navigate the user to the previous page, and similarly, getCanNextPage will return a boolean value if the user can go to the next page and nextPage will move current view to the next page.

Finally, we can build the necessary UI at the bottom of the table for the user to navigate.

// ... existing code …
import {
// ... existing code ...
HStack,
IconButton,
Heading,
} from "@chakra-ui/react";
import {
ArrowBackIcon,
ArrowForwardIcon,
ArrowLeftIcon,
ArrowRightIcon,
} from "@chakra-ui/icons";
// ... existing code ...
<HStack align="center" justify="center" m={4}>
<IconButton
icon={<ArrowLeftIcon />}
onClick={() => firstPage()}
aria-label=""
>
First Page
</IconButton>
<IconButton
icon={<ArrowBackIcon />}
isDisabled={!getCanPreviousPage()}
onClick={() => previousPage()}
aria-label=""
>
Prev Page
</IconButton>
<IconButton
icon={<ArrowForwardIcon />}
isDisabled={!getCanNextPage()}
onClick={() => nextPage()}
aria-label=""
>
Next Page
</IconButton>
<IconButton
icon={<ArrowRightIcon />}
onClick={() => lastPage()}
aria-label=""
>
Last Page
</IconButton>
</HStack>
// ... existing code ...

Below is all the combined code that we will need for implementing table pagination.

import {
// ... existing code ...
getPaginationRowModel,
} from "@tanstack/react-table";
import {
// ... existing code ...
HStack,
IconButton,
Heading,
} from "@chakra-ui/react";
import {
ArrowBackIcon,
ArrowForwardIcon,
ArrowLeftIcon,
ArrowRightIcon,
} from "@chakra-ui/icons";
export const ReactTable = () => {
// ... existing code ...
const table = useReactTable({
// ... existing code ...
getPaginationRowModel: getPaginationRowModel(),
});
const {
getHeaderGroups,
getRowModel,
firstPage,
previousPage,
lastPage,
nextPage,
getCanNextPage,
getCanPreviousPage,
} = table;
return (
<TableContainer p={8}>
<Heading>React Table Example</Heading>
<Input
value={globalFilter || ""}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder="Search all columns..."
my={4}
/>
<Table>
// ... existing code ...
</Table>
<HStack align="center" justify="center" m={4}>
<IconButton
icon={<ArrowLeftIcon />}
onClick={() => firstPage()}
aria-label=""
>
First Page
</IconButton>
<IconButton
icon={<ArrowBackIcon />}
isDisabled={!getCanPreviousPage()}
onClick={() => previousPage()}
aria-label=""
>
Prev Page
</IconButton>
<IconButton
icon={<ArrowForwardIcon />}
isDisabled={!getCanNextPage()}
onClick={() => nextPage()}
aria-label=""
>
Next Page
</IconButton>
<IconButton
icon={<ArrowRightIcon />}
onClick={() => lastPage()}
aria-label=""
>
Last Page
</IconButton>
</HStack>
</TableContainer>
);
}

Sorting

To add sorting functionality to our table, we will need to create a state variable for storing the sorting state. We will then need to pass the sorting state sorting and its setter function setSorting and getSortedRowModel while creating the table instance.

// ... existing code ...
import { getSortedRowModel, SortingState } from "@tanstack/react-table";
export const ReactTable = () => {
// ... existing code ...
const [sorting, setSorting] = useState<SortingState>([]);
// ... existing code ...
const table = useReactTable({
// ... existing code ...
state: {
globalFilter,
sorting,
},
getSortedRowModel: getSortedRowModel(),
onSortingChange: setSorting,
});

Now we can add an onClick event to the header of each column which will toggle the sorting between ascending, descending, and none as shown below.

<Thead>
{getHeaderGroups().map((headerGroup) => (
<Tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<Th
key={header.id}
onClick={header.column.getToggleSortingHandler()}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
{header.column.getIsSorted() === "asc" && <ArrowUpIcon />}
{header.column.getIsSorted() === "desc" && <ArrowDownIcon />}
</Th>
))}
</Tr>
))}
</Thead>

Below is all the combined code that we will need for implementing table sorting.

// ... existing code ...
import {
// ... existing code ...
getSortedRowModel,
SortingState,
} from "@tanstack/react-table";
export const ReactTable = () => {
// ... existing code ...
const [sorting, setSorting] = useState<SortingState>([]);
// ... existing code ...
const table = useReactTable({
// ... existing code ...
state: {
globalFilter,
sorting,
},
getSortedRowModel: getSortedRowModel(),
onSortingChange: setSorting,
});
return (
// ... existing code ...
<Thead>
{getHeaderGroups().map((headerGroup) => (
<Tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<Th
key={header.id}
onClick={header.column.getToggleSortingHandler()}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
{header.column.getIsSorted() === "asc" && <ArrowUpIcon />}
{header.column.getIsSorted() === "desc" && <ArrowDownIcon />}
</Th>
))}
</Tr>
))}
</Thead>
// ... existing code ...
)

After combining all these functionalities of filtering, sorting and pagination here is how our final component looks like

import {
ArrowBackIcon,
ArrowDownIcon,
ArrowForwardIcon,
ArrowLeftIcon,
ArrowRightIcon,
ArrowUpIcon,
} from "@chakra-ui/icons";
import {
Heading,
HStack,
IconButton,
Input,
Table,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr,
} from "@chakra-ui/react";
import {
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
SortingState,
useReactTable,
} from "@tanstack/react-table";
import { useEffect, useMemo, useState } from "react";
import { getTableData } from "../../../api.ts";
import { IEmployee } from "../../../utils/types.ts";
import { COLUMNS } from "./columns.ts";
export const ReactTable = () => {
const columns = useMemo(() => COLUMNS, []);
const [data, setData] = useState<IEmployee[]>([]);
const [globalFilter, setGlobalFilter] = useState("");
const [sorting, setSorting] = useState<SortingState>([]);
useEffect(() => {
const fetchData = async () => {
const { datasets } = await getTableData();
setData(datasets);
console.log(datasets);
};
fetchData();
}, []);
const table = useReactTable({
columns,
data,
state: {
globalFilter,
sorting,
},
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onGlobalFilterChange: setGlobalFilter,
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
onSortingChange: setSorting,
});
const {
getHeaderGroups,
getRowModel,
firstPage,
previousPage,
lastPage,
nextPage,
getCanNextPage,
getCanPreviousPage,
} = table;
return (
<TableContainer p={8}>
<Heading>React Table Example</Heading>
<Input
value={globalFilter || ""}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder="Search all columns..."
my={4}
/>
<Table>
<Thead>
{getHeaderGroups().map((headerGroup) => (
<Tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<Th
key={header.id}
onClick={header.column.getToggleSortingHandler()}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
{header.column.getIsSorted() === "asc" && <ArrowUpIcon />}
{header.column.getIsSorted() === "desc" && <ArrowDownIcon />}
</Th>
))}
</Tr>
))}
</Thead>
<Tbody>
{getRowModel().rows.map((row) => (
<Tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<Td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</Td>
))}
</Tr>
))}
</Tbody>
</Table>
<HStack align="center" justify="center" m={4}>
<IconButton
icon={<ArrowLeftIcon />}
onClick={() => firstPage()}
aria-label=""
>
First Page
</IconButton>
<IconButton
icon={<ArrowBackIcon />}
isDisabled={!getCanPreviousPage()}
onClick={() => previousPage()}
aria-label=""
>
Prev Page
</IconButton>
<IconButton
icon={<ArrowForwardIcon />}
isDisabled={!getCanNextPage()}
onClick={() => nextPage()}
aria-label=""
>
Next Page
</IconButton>
<IconButton
icon={<ArrowRightIcon />}
onClick={() => lastPage()}
aria-label=""
>
Last Page
</IconButton>
</HStack>
</TableContainer>
);
};

Here is a quick demo of what we have built so far

#Reusing our table

With the current example, we have displayed employee data, but it cannot be extended further to display product data, or order data, or any other data. To make it reusable, we need to decouple the parts specific to the data i.e. the data and the columns. We should extract the data fetching logic and the columns in a parent component and pass the data and columns as props to our ReactTable component. This way our ReactTable can be repurposed for displaying any type of data.

First, remove data and column-related code from our ReactTable component and create a new EmployeeTable component that will have context around “Employee” related things, and the ReactTable component will not even have the context that it is displaying employees.

EmployeeTable.tsx

import { useEffect, useMemo, useState } from "react";
import { getTableData } from "../../../api.ts";
import { IEmployee } from "../../../utils/types.ts";
import { ReactTable } from "./react-table.tsx";
import { COLUMNS } from "./columns.ts";
export const EmployeeTable = () => {
const columns = useMemo(() => COLUMNS, []);
const [data, setData] = useState<IEmployee[]>([]);
useEffect(() => {
const fetchData = async () => {
const { datasets } = await getTableData();
setData(datasets);
};
fetchData();
}, []);
return <ReactTable<IEmployee> data={data} columns={columns} />;
};
Use Typescript generics to define our `ReactTable` props and destructure those props in the function definition.
interface ReactTableProps<T> {
data: T[],
columns: ColumnDef<T>[]
}
export const ReactTable = <T,>({ columns, data }: ReactTableProps<T>) => {
// ... existing code ...
// ... without data & columns ...
}

That’s it, now we have our final reusable ReactTable component, cheers!

import {
ArrowBackIcon,
ArrowDownIcon,
ArrowForwardIcon,
ArrowLeftIcon,
ArrowRightIcon,
ArrowUpIcon,
} from "@chakra-ui/icons";
import {
Heading,
HStack,
IconButton,
Input,
Table,
TableContainer,
Tbody,
Td,
Th,
Thead,
Tr,
} from "@chakra-ui/react";
import {
ColumnDef,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
SortingState,
useReactTable,
} from "@tanstack/react-table";
import { useState } from "react";
interface ReactTableProps<T> {
data: T[],
columns: ColumnDef<T>[]
}
export const ReactTable = <T,>({ columns, data }: ReactTableProps<T>) => {
const [globalFilter, setGlobalFilter] = useState("");
const [sorting, setSorting] = useState<SortingState>([]);
const table = useReactTable({
columns,
data,
state: {
globalFilter,
sorting,
},
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onGlobalFilterChange: setGlobalFilter,
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
onSortingChange: setSorting,
});
const {
getHeaderGroups,
getRowModel,
firstPage,
previousPage,
lastPage,
nextPage,
getCanNextPage,
getCanPreviousPage,
} = table;
return (
<TableContainer p={8}>
<Heading>React Table Example</Heading>
<Input
value={globalFilter || ""}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder="Search all columns..."
my={4}
/>
<Table>
<Thead>
{getHeaderGroups().map((headerGroup) => (
<Tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<Th
key={header.id}
onClick={header.column.getToggleSortingHandler()}
>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
{header.column.getIsSorted() === "asc" && <ArrowUpIcon />}
{header.column.getIsSorted() === "desc" && <ArrowDownIcon />}
</Th>
))}
</Tr>
))}
</Thead>
<Tbody>
{getRowModel().rows.map((row) => (
<Tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<Td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</Td>
))}
</Tr>
))}
</Tbody>
</Table>
<HStack align="center" justify="center" m={4}>
<IconButton
icon={<ArrowLeftIcon />}
onClick={() => firstPage()}
aria-label=""
>
First Page
</IconButton>
<IconButton
icon={<ArrowBackIcon />}
isDisabled={!getCanPreviousPage()}
onClick={() => previousPage()}
aria-label=""
>
Prev Page
</IconButton>
<IconButton
icon={<ArrowForwardIcon />}
isDisabled={!getCanNextPage()}
onClick={() => nextPage()}
aria-label=""
>
Next Page
</IconButton>
<IconButton
icon={<ArrowRightIcon />}
onClick={() => lastPage()}
aria-label=""
>
Last Page
</IconButton>
</HStack>
</TableContainer>
);
};

#Conclusion

In this guide, we have learned how and when to use the React table library in our application. We fetched data on runtime from a HyGraph API and displayed that data in a tabular format using the React Table APIs. We further explored the library and available APIs for utilities like filtering, pagination, and sorting. Finally, we extracted our table component passing it data and column as props, so it can be repurposed for various use cases.

Blog Authors

Share with others

Sign up for our newsletter!

Be the first to know about releases and industry news and insights.