React Responsive Data Table with Pagination, Sorting, Filtering Tutorial

React responsive data table tutorial; This pragmatic yet comprehensive guide will describe how to effortlessly build responsive and dynamic DataTables in React application with the help of react-table and styled-components packages.

Besides, learn how to integrate advanced features in the data table such as sorting, pagination, row resizing and expansion, etc., from absolute scratch.

Data tables offer a facile way to demonstrate data in web layout; imagine how difficult it is to display information to the users. User experience plays a vital role in engaging site visitors, no matter how beautiful your layout is. Still, if it lacks a great user experience, you may lose the users’ interest related to your site.

Creating a data table in react is simple, you don’t have to perform old rituals to integrate in react. This is only because of the react-table package; it allows you to build profound dynamic data tables with advanced features like sorting, filter, pagination, etc.

Here is the list of handy features you get with react-table plugin.

  • Lightweight (5kb – 14kb+ depending on features used and tree-shaking)
  • Headless (100% customizable, Bring-your-own-UI)
  • Auto out of the box, fully controllable API
  • Sorting (Multi and Stable)
  • Filters
  • Row Selection
  • Row Expansion
  • Column Ordering
  • Animatable
  • Virtualizable
  • Resizable
  • Pivoting & Aggregation
  • Server-side/controlled data/state
  • Extensible via a hook-based plugin system

How to Create Dynamic DataTable in React

  • Step 1: Install React App
  • Step 2: Add react-table Package
  • Step 3: Install Bootstrap Package
  • Step 4: Create Reusable Component
  • Step 5: Create Simple Data Table
  • Step 6: Add Pagination in React Data Table
  • Step 7: Implement Sorting in Data Table
  • Step 8: Start React Project

Install React App

We assume you have set up the react environment on your system, open the terminal, type the given command on the command prompt and start installing the React app.

npx create-react-app react-blog-app

After that, get inside the project.

cd react-blog-app

Install react-table Package

In this section, we will add the react-table package to build a reusable data table component in react app.

npm install react-table

Install Bootstrap Package

You need to execute the following command to start downloading bootstrap package in react.

npm install bootstrap

Create React Reusable Component

Inside the src folder, create components folder, also create datatable.component.js file, after that add the following code in the src/components/datatable.component.js file.

Next, you need to register the datatable component in the main src/App.js file.


import React from 'react';

import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import './App.css';
import DataTableComponent from './components/datatable.component';


function App() {
  return (
    <div className="App">
      <div className="container mt-5">
        <DataTableComponent />
      </div>
    </div>
  );
}

export default App;

Create Simple Data Table

Forming a datatable requires adding data; consequently, we need to create the data and the columns variables. The data variable holds the user information such as name, email, and phone number, whereas columns hold the table header properties.

The Bootstrap UI components are helping us here to style the table component.

Insert the following code in the src/components/datatable.component.js file

import React from 'react';
import { useTable } from 'react-table'

function DataTableComponent() {

  const data = [
    {
      name: 'Sara Turner',
      email: 'sara.turner@example.com',
      phone: '(603)-641-0238'
    },
    {
      name: 'Christian Kelley',
      email: 'christian.kelley@example.com',
      phone: '(153)-324-6597'
    },
    {
      name: 'Annie Dean',
      email: 'annie.dean@example.com',
      phone: '(373)-005-2708'
    },
    {
      name: 'Cameron Hunt',
      email: 'cameron.hunt@example.com',
      phone: '(912)-351-7665'
    },
    {
      name: 'Brandon Cook',
      email: 'brandon.cook@example.com',
      phone: '(554)-103-5975'
    },
    {
      name: 'Ashley Jones',
      email: 'ashley.jones@example.com',
      phone: '(604)-896-2642'
    },
    {
      name: 'Allan Fields',
      email: 'allan.fields@example.com',
      phone: '(197)-032-6069'
    },
    {
      name: 'Justin Barnes',
      email: 'justin.barnes@example.com',
      phone: '(002)-902-1774'
    },
    {
      name: 'Willie Jordan',
      email: 'willie.jordan@example.com',
      phone: '(535)-969-6902'
    },
    {
      name: 'Rhonda Cooper',
      email: 'rhonda.cooper@example.com',
      phone: '(746)-018-4462'
    },                           
  ]

  const columns = [
    {
      Header: 'Name',
      accessor: 'name'
    }, {
      Header: 'Email',
      accessor: 'email'
    }, {
      Header: 'Phone',
      accessor: 'phone'
    }
  ]

  const {
      rows,
      prepareRow,
      getTableProps,
      headerGroups,
      getTableBodyProps,
  } = useTable({
      columns,
      data,
  })

  return (
<div className="card">
  <div className="card-body">
        <table className="table table-light" {...getTableProps()}>
            <thead>
                {headerGroups.map(headerGroup => (
                    <tr {...headerGroup.getHeaderGroupProps()}>
                        {headerGroup.headers.map(data => (
                            <th {...data.getHeaderProps()}>{data.render('Header')}</th>
                        ))}
                    </tr>
                ))}
            </thead>
            <tbody {...getTableBodyProps()}>
                {rows.map((row, i) => {
                    prepareRow(row)
                    return (
                        <tr {...row.getRowProps()}>
                            {row.cells.map(cell => {
                                return <td {...cell.getCellProps()}> {cell.render('Cell')} </td>
                            })}
                        </tr>
                    )
                })}
            </tbody>
        </table>
    </div>
  </div>
  )
}

export default DataTableComponent;

Add Pagination in React Data Table

Import usePagination just beside the useTable API, create Table function, we need to define few properties to enable pagination in react datatable, primarily a table requires data and column values. Open and update the datatable.component.js file.

import React from 'react';
import { useTable, usePagination } from 'react-table'

function Table({columns, data}) {
  const {
    page,
    getTableProps,
    getTableBodyProps,
    headerGroups,
    prepareRow,
    canPreviousPage,
    canNextPage,
    pageOptions,
    pageCount,
    gotoPage,
    nextPage,
    previousPage,
    setPageSize,
    state: { pageIndex, pageSize },
  } = useTable(
    {
      columns,
      data,
      initialState: { pageIndex: 0 },
    },
    usePagination
  )

  return (
    <>
      <div className="card">
        <div className="card-body">
              <table className="table table-light" {...getTableProps()}>
              <thead>
                {headerGroups.map(headerGroup => (
                  <tr {...headerGroup.getHeaderGroupProps()}>
                    {headerGroup.headers.map(column => (
                      <th {...column.getHeaderProps()}>{column.render('Header')}</th>
                    ))}
                  </tr>
                ))}
              </thead>
              <tbody {...getTableBodyProps()}>
                {page.map((row, i) => {
                  prepareRow(row)
                  return (
                    <tr {...row.getRowProps()}>
                      {row.cells.map(cell => {
                        return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                      })}
                    </tr>
                  )
                })}
              </tbody>
            </table>  

          <div className="pagination">
                  <button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
                    {'<<'}
                  </button>{' '}
                  <button onClick={() => previousPage()} disabled={!canPreviousPage}>
                    {'<'}
                  </button>{' '}
                  <button onClick={() => nextPage()} disabled={!canNextPage}>
                    {'>'}
                  </button>{' '}
                  <button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
                    {'>>'}
                  </button>{' '}
                  <span>
                    Page{' '}
                    <strong>
                      {pageIndex + 1} of {pageOptions.length}
                    </strong>{' '}
                  </span>
                  <span>
                    | Go to page:{' '}
                    <input
                      type="number"
                      defaultValue={pageIndex + 1}
                      onChange={e => {
                        const page = e.target.value ? Number(e.target.value) - 1 : 0
                        gotoPage(page)
                      }}
                      style={{ width: '100px' }}
                    />
                  </span>{' '}
                  <select
                    value={pageSize}
                    onChange={e => {
                      setPageSize(Number(e.target.value))
                    }}
                  >
                    {[3, 7, 15].map(pageSize => (
                      <option key={pageSize} value={pageSize}>
                        Show {pageSize}
                      </option>
                    ))}
                  </select>
              </div>
            </div>
      </div>
    </>

  )
}

function DataTableComponent() {
  const data = [
    {
      name: 'Sara Turner',
      email: 'sara.turner@example.com',
      phone: '(603)-641-0238'
    },
    {
      name: 'Christian Kelley',
      email: 'christian.kelley@example.com',
      phone: '(153)-324-6597'
    },
    {
      name: 'Annie Dean',
      email: 'annie.dean@example.com',
      phone: '(373)-005-2708'
    },
    {
      name: 'Cameron Hunt',
      email: 'cameron.hunt@example.com',
      phone: '(912)-351-7665'
    },
    {
      name: 'Brandon Cook',
      email: 'brandon.cook@example.com',
      phone: '(554)-103-5975'
    },
    {
      name: 'Ashley Jones',
      email: 'ashley.jones@example.com',
      phone: '(604)-896-2642'
    },
    {
      name: 'Allan Fields',
      email: 'allan.fields@example.com',
      phone: '(197)-032-6069'
    },
    {
      name: 'Justin Barnes',
      email: 'justin.barnes@example.com',
      phone: '(002)-902-1774'
    },
    {
      name: 'Willie Jordan',
      email: 'willie.jordan@example.com',
      phone: '(535)-969-6902'
    },
    {
      name: 'Rhonda Cooper',
      email: 'rhonda.cooper@example.com',
      phone: '(746)-018-4462'
    },
    {
      name: 'Sara Turner',
      email: 'sara.turner@example.com',
      phone: '(603)-641-0238'
    },
    {
      name: 'Christian Kelley',
      email: 'christian.kelley@example.com',
      phone: '(153)-324-6597'
    },
    {
      name: 'Annie Dean',
      email: 'annie.dean@example.com',
      phone: '(373)-005-2708'
    },
    {
      name: 'Cameron Hunt',
      email: 'cameron.hunt@example.com',
      phone: '(912)-351-7665'
    },
    {
      name: 'Brandon Cook',
      email: 'brandon.cook@example.com',
      phone: '(554)-103-5975'
    },
    {
      name: 'Ashley Jones',
      email: 'ashley.jones@example.com',
      phone: '(604)-896-2642'
    },
    {
      name: 'Allan Fields',
      email: 'allan.fields@example.com',
      phone: '(197)-032-6069'
    },
    {
      name: 'Justin Barnes',
      email: 'justin.barnes@example.com',
      phone: '(002)-902-1774'
    },
    {
      name: 'Willie Jordan',
      email: 'willie.jordan@example.com',
      phone: '(535)-969-6902'
    },
    {
      name: 'Rhonda Cooper',
      email: 'rhonda.cooper@example.com',
      phone: '(746)-018-4462'
    }    
  ]

  const columns = [
    {
      Header: 'Name',
      accessor: 'name'
    }, {
      Header: 'Email',
      accessor: 'email'
    }, {
      Header: 'Phone',
      accessor: 'phone'
    }
  ]

  return (
      <Table data={data} columns={columns}/>
  )

}

export default DataTableComponent

Implement Sorting in Data Table

In this last example, we will explain the simple way to integrate sorting functionality in react data table. Why is data sorting important, and what is it? In general, data sorting is a simple process that includes managing data in proper order for easier visualization and understandability. Ideally, data is arranged or sorted in either ascending or descending order or original values such as percentages and counts.

import React from 'react';
import { useTable, useSortBy } from 'react-table'

function Table({columns, data}) {
  const {
    rows,
    getTableProps,
    getTableBodyProps,
    prepareRow,
    headerGroups,
  }  = useTable(
    {
      columns,
      data,
    },
    useSortBy
  )

  const initRow = rows.slice(0, 20)


  return (
    <>
      <div className="card">
          <div className="card-body">
              <table className="table table-light" {...getTableProps()}>
              <thead>
          {headerGroups.map(headerGroup => (
            <tr {...headerGroup.getHeaderGroupProps()}>
              {headerGroup.headers.map(column => (
                <th {...column.getHeaderProps(column.getSortByToggleProps())}>
                  {column.render('Header')}
                  <span>
                    {column.isSorted
                      ? column.isSortedDesc
                        ? ' đź”˝'
                        : ' 🔼'
                      : ''}
                  </span>
                </th>
              ))}
            </tr>
          ))}
        </thead>
        <tbody {...getTableBodyProps()}>
          {initRow.map(
            (row, i) => {
              prepareRow(row);
              return (
                <tr {...row.getRowProps()}>
                  {row.cells.map(cell => {
                    return (
                      <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
                    )
                  })}
                </tr>
              )}
          )}
        </tbody>               
              </table>  
          </div>
      </div>
    </>

  )
}

function DataTableComponent() {
  const data = [
    {
      name: 'Sara Turner',
      email: 'sara.turner@example.com',
      phone: '(603)-641-0238'
    },
    {
      name: 'Christian Kelley',
      email: 'christian.kelley@example.com',
      phone: '(153)-324-6597'
    },
    {
      name: 'Annie Dean',
      email: 'annie.dean@example.com',
      phone: '(373)-005-2708'
    },
    {
      name: 'Cameron Hunt',
      email: 'cameron.hunt@example.com',
      phone: '(912)-351-7665'
    },
    {
      name: 'Brandon Cook',
      email: 'brandon.cook@example.com',
      phone: '(554)-103-5975'
    },
    {
      name: 'Ashley Jones',
      email: 'ashley.jones@example.com',
      phone: '(604)-896-2642'
    },
    {
      name: 'Allan Fields',
      email: 'allan.fields@example.com',
      phone: '(197)-032-6069'
    },
    {
      name: 'Justin Barnes',
      email: 'justin.barnes@example.com',
      phone: '(002)-902-1774'
    },
    {
      name: 'Willie Jordan',
      email: 'willie.jordan@example.com',
      phone: '(535)-969-6902'
    },
    {
      name: 'Rhonda Cooper',
      email: 'rhonda.cooper@example.com',
      phone: '(746)-018-4462'
    },
    {
      name: 'Sara Turner',
      email: 'sara.turner@example.com',
      phone: '(603)-641-0238'
    },
    {
      name: 'Christian Kelley',
      email: 'christian.kelley@example.com',
      phone: '(153)-324-6597'
    },
    {
      name: 'Annie Dean',
      email: 'annie.dean@example.com',
      phone: '(373)-005-2708'
    },
    {
      name: 'Cameron Hunt',
      email: 'cameron.hunt@example.com',
      phone: '(912)-351-7665'
    },
    {
      name: 'Brandon Cook',
      email: 'brandon.cook@example.com',
      phone: '(554)-103-5975'
    },
    {
      name: 'Ashley Jones',
      email: 'ashley.jones@example.com',
      phone: '(604)-896-2642'
    },
    {
      name: 'Allan Fields',
      email: 'allan.fields@example.com',
      phone: '(197)-032-6069'
    },
    {
      name: 'Justin Barnes',
      email: 'justin.barnes@example.com',
      phone: '(002)-902-1774'
    },
    {
      name: 'Willie Jordan',
      email: 'willie.jordan@example.com',
      phone: '(535)-969-6902'
    },
    {
      name: 'Rhonda Cooper',
      email: 'rhonda.cooper@example.com',
      phone: '(746)-018-4462'
    }    
  ]

  const columns = [
    {
      Header: 'Name',
      accessor: 'name'
    }, {
      Header: 'Email',
      accessor: 'email'
    }, {
      Header: 'Phone',
      accessor: 'phone'
    }
  ]

  return (
      <Table data={data} columns={columns}/>
  )

}

export default DataTableComponent

Start React Project

In the last section of this guide, you require to start the react application similarly execute the following command.

npm start

Given below url manifests on the terminal window, make sure to use to run the app.

http://localhost:3000

React datatable example

Conclusion

The React datatable example is ended; Throughout this tutorial, we tried to intensify the process of explaining how to add datatable in react app using the react-table library. Not just that, we also described how to use styled components to design the react datatable using CSS.