In this article, we will talk about react table. By the way – check our previous article about Bootstrap table! We won’t talk much about how important tables are in modern web development and also skip unnecessary info to keep the intro short. Instead, we will give you good concentrated information on how to choose a react table, what difficulties are there during the development of react table, and other things that will really help you create great and useful react tables. Even more, we also made a small guide for you on building a react table based on the most popular react-table library.

How to choose a React table library

In order to choose the right react table, you need to decide what functions it will perform. For example, whether you need pagination or sorting. Think of the features you need and choose the react table library that fits them.

React, Angular, Vue and Bootstrap templates

In Flatlogic we create web & mobile application templates built with React, Vue, Angular and React Native to help you develop web & mobile apps faster. Go and check out yourself!
See our themes!

It is also worth deciding whether you are willing to pay for the library or not. Paid versions of the react tables libraries have a very wide range of features that will help you develop it.

Now let’s see how this looks like in real-life examples:

  • If you need a simple page with a small amount of data, custom styles, and minimum number of features like sorting and filtering, we recommend to use react-table;
  • If you want a mini Google Sheets, use react-data-grid or react-datasheet;
  • If you need to manipulate very large amounts of information, then we recommend using react – virtualize or paid libraries such as React data grid of Syncfusion.

Features of a good React Table

Developing a good react table is a difficult challenge that you must definitely go through. And the challenge is that a good react table must simultaneously correspond to several requirements – responsiveness, speed, readability, etc. Let’s take a closer look at each of these.

React table must be responsive

It is very important for react data tables to be displayed correctly on all types of screens. Usually this is solved by the columns decrease in width and increase in length, but this solution is not always optimal for the user experience.

Do you like this article?
You might want to read:

Top 30 Open Source and Paid React Charts + Examples

React table must Be Readable

Tables often provide information that is very difficult to read, manipulate, and edit. A good spreadsheet shows information so that it is clearly readable and well-parsed, even if you have hundreds and thousands of lines. A flexible react data table solution can account for long strings of data without creating misalignment or compromising readability.

React table needs to be fast

Another important feature of a good react table is the speed of working with data – i.e. filtering and sorting. Good UX often depends on application speed.

React Table UI challenges

There are many aspects that need to be taken into account when we work with tables. Let’s define them.

Filtering and sorting data

It is very important to make these basic functions work quickly and intuitively – these are the two main functions that define a table as an element.

Check out premium React Themes and Templates for $299!

  • 10 premium templates 
  • 1,000 unique components
  • 300 pages

Styles

Good react table need to be styled: well-done styles can make tables readable and nice to look at. For example, an easy selection of cells with a hover when you hover over them will help users understand which cell they are in.

Responsiveness

It’s difficult to make a table responsive without changing the layout to suit smaller screen sizes. Responsive tables often look and perform awful. Therefore, the task of showing the table on different size screens looks complicated. Features such as pagination can help you with this.

Scrolling

Default browser scrollbars will work well for full-width tables, but most have custom width. The solution is developing a custom scroll bar, or implementing one from ready made libraries. However, custom scrollbars are very tricky to support on both touch and non-touch screens.

Right positioning of the table 

It is also important to correctly position the react table relative to other elements on the screen, so that you can work with it efficiently and read information properly.

React table Guide

Now that we know a bit more about React table, let’s have a look at the development of different types of react tables. We’ll use the most popular react-table library as the example. We will obviously use create-react-app boilerplate for better development speed.
The first thing you need to do is install the react-table library itself. To do this, run npm install react-table or yarn add react-table in the following command. After you enter these commands, check the package.json file, you should see the following entry:

"dependencies": {
 "react-table": "^7.1.0"
}

Additionally if you want to modify styles, please edit src/index.css file.

To begin with, we will build the simplest react table with 3 columns and 3 rows. Each column will have its own separate one header. In this example, we will not build multi-level constructs with grouped headers.

Basic react table

basic react table

React-table, like other libraries, consist of:

  • Columns – an array of columns. Columns can be nested, which act as header groups. In addition, columns can be recursively nested as much as needed;
  • Data is an array of rows to be displayed on the table.

To build a react table you will need a dataset. In our case, we did not create any separate files in the form of json objects: for speed reasons we created these objects directly in App.js.

Here’s what an example code looks like for a simple table based on the React-tables library:

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

function Example() {

 const data = React.useMemo(
     () => [
       {
         col1: 'Minsk',
         col2: '27',
         col3: 'rain',
       },
       {
         col1: 'Vilnius',
         col2: '30',
         col3: 'rain',
       },
       {
         col1: 'London',
         col2: '23',
         col3: 'rain',
       },
     ],
     []
 )

 const columns = React.useMemo(
     () => [
       {
         Header: 'City',
         accessor: 'col1', // accessor is the "key" in the data
       },
       {
         Header: 'Temperature',
         accessor: 'col2',
       },
       {
         Header: 'Weather Forecast',
         accessor: 'col3', // accessor is the "key" in the data
       },
     ],
     []
 )

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

 return (
     <div>
       <table {...getTableProps()} style={{ border: 'solid 1px black }}>
         <thead>
         {headerGroups.map(headerGroup => (
             <tr {...headerGroup.getHeaderGroupProps()}>
               {headerGroup.headers.map(column => (
                   <th
                       {...column.getHeaderProps()}
                       style={{
                         borderBottom: 'solid 3px red',
                         color: 'black',
                       }}
                   >
                     {column.render('Header')}
                   </th>
               ))}
             </tr>
         ))}
         </thead>
         <tbody {...getTableBodyProps()}>
         {rows.map(row => {
           prepareRow(row)
           return (
               <tr {...row.getRowProps()}>
                 {row.cells.map(cell => {
                   return (
                       <td
                           {...cell.getCellProps()}
                           style={{
                             padding: '10px',
                             border: 'solid 1px gray',
                           }}
                       >
                         {cell.render('Cell')}
                       </td>
                   )
                 })}
               </tr>
           )
         })}
         </tbody>
       </table>
     </div>
 );
}

export default Example;

Note that the spread operator is used to expand the expression more easily.

All the columns we have an accessor, which is the data we have in the data object. Our data is inside the show object in the array — that’s why all our accessors have show as a prefix.

Also, let’s explain a little what the functions and hooks used in the code above mean:

  • useTable hook takes options and plugins to build a table instance. The basic options are columns and data. 
  • getTableProps is a function to resolve any props needed by the table wrapper. Built-in table props are {role: “table”}, which can be customized.
  • getTableBodyProps is a function to resolve any props needed by the table body wrapper. The built-in table props are {role: “rowgroup”}, which can be customized.
  • prepareRow is a function that must be called on any row to be displayed. It is responsible for preparing a row for rendering.
  • headerGroups and rows are internal data structures derived from columns and data.

React Table with Sorting

Row sorting is a basic and a must functionality for the react table. To implement sorting of the columns in react-table you need to use useSortBy hook plugin which is optional. We have received the following result:

react-table sorting

The update code of src/App.js looks like this:

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

function Example() {

 const data = React.useMemo(
     () => [
       {
         col1: 'Minsk',
         col2: '27',
         col3: 'rain',
       },
       {
         col1: 'Vilnius',
         col2: '30',
         col3: 'rain',
       },
       {
         col1: 'London',
         col2: '23',
         col3: 'rain',
       },
     ],
     []
 )

 const columns = React.useMemo(
     () => [
       {
         Header: 'City',
         accessor: 'col1', // accessor is the "key" in the data
       },
       {
         Header: 'Temperature',
         accessor: 'col2',
       },
       {
         Header: 'Weather Forecast',
         accessor: 'col3', // accessor is the "key" in the data
       },
     ],
     []
 )

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

 return (
     <div>
       <table {...getTableProps()} style={{ border: 'solid 1px black' }}>
         <thead>
         {headerGroups.map(headerGroup => (
             <tr {...headerGroup.getHeaderGroupProps()}>
               {headerGroup.headers.map(column => (
                   <th
                       {...column.getHeaderProps(column.getSortByToggleProps())}
                       style={{
                         borderBottom: 'solid 3px red',
                         color: 'black',
                       }}
                   >
                     {column.render('Header')}
                     <span>
                       {column.isSorted
                           ? column.isSortedDesc
                               ? '🔽'
                               : '🔼'
                           : ''}
                    </span>
                   </th>
               ))}
             </tr>
         ))}
         </thead>
         <tbody {...getTableBodyProps()}>
         {rows.map(row => {
           prepareRow(row)
           return (
               <tr {...row.getRowProps()}>
                 {row.cells.map(cell => {
                   return (
                       <td
                           {...cell.getCellProps()}
                           style={{
                             padding: '10px',
                             border: 'solid 1px gray',
                           }}
                       >
                         {cell.render('Cell')}
                       </td>
                   )
                 })}
               </tr>
           )
         })}
         </tbody>
       </table>
     </div>
 );
}

export default Example;

We used the useSortBy plugin after declaring useTable hook.

getSortByToggleProps() is a function that resolves any props needed while toggling the sort direction.

Lines 29 to 31 display a descending or ascending arrow for the sorted column.

The sorting works in a following way:

Clicking a column header will toggle between ascending, descending, and no sort. If you shift-click a column header, the other column sort states will be preserved and the new column will be sorted afterwards. This ends up with multi-sort.

Filtering React Table

This is another default function for React-table. To do this, we add useFilters and useGlobalFilter hooks to our code. The difference between these two hooks is that the first is responsible for filtering a specific column, while the global filter works on the entire table – any column and row.

react-table filtering

The code in this case will look like this:

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

function GlobalFilter({
                       preGlobalFilteredRows,
                       globalFilter,
                       setGlobalFilter,
                     }) {
 const count = preGlobalFilteredRows.length
 const [value, setValue] = React.useState(globalFilter)
 const onChange = useAsyncDebounce(value => {
   setGlobalFilter(value || undefined)
 }, 200)

 return (
   <span>
     Search:{' '}
     <input
       value={value || ""}
       onChange={e => {
         setValue(e.target.value);
         onChange(e.target.value);
       }}
       placeholder={`${count} records...`}
       style={{
         fontSize: '1.1rem',
         border: '0',
       }}
     />
   </span>
 )
}

// Define a default UI for filtering
function DefaultColumnFilter({
                              column: { filterValue, preFilteredRows, setFilter },
                            }) {
 const count = preFilteredRows.length

 return (
   <input
     value={filterValue || ''}
     onChange={e => {
       setFilter(e.target.value || undefined) // Set undefined to remove the filter entirely
     }}
     placeholder={`Search ${count} records...`}
   />
 )
}

function Example() {

 const data = React.useMemo(
     () => [
       {
         col1: 'Minsk',
         col2: '27',
         col3: 'rain',
         col4: '739',
         col5: '90',
       },
       {
         col1: 'Vilnius',
         col2: '30',
         col3: 'rain',
         col4: '740',
         col5: '87',
       },
       {
         col1: 'London',
         col2: '23',
         col3: 'rain',
         col4: '743',
         col5: '77',
       },
       {
         col1: 'Madrid',
         col2: '34',
         col3: 'sunny',
         col4: '738',
         col5: '40',
       },
       {
         col1: 'Warsaw',
         col2: '25',
         col3: 'heavy rain',
         col4: '739',
         col5: '88',
       },
     ],
     []
 )

 const columns = React.useMemo(
     () => [
       {
         Header: 'City',
         accessor: 'col1', // accessor is the "key" in the data
       },
       {
         Header: 'Temperature',
         accessor: 'col2',
       },
       {
         Header: 'Weather Forecast',
         accessor: 'col3',
       },
       {
         Header: 'Pressure',
         accessor: 'col4',
       },
       {
         Header: 'Humidity',
         accessor: 'col5',
       },
     ],
     []
 )

 const defaultColumn = React.useMemo(
   () => ({
     // Let's set up our default Filter UI
     Filter: DefaultColumnFilter,
   }),
   []
 )

 const {
   getTableProps,
   getTableBodyProps,
   headerGroups,
   rows,
   prepareRow,
   state,
   visibleColumns,
   preGlobalFilteredRows,
   setGlobalFilter,
 } = useTable(
   {
     columns,
     data,
     defaultColumn, // Be sure to pass the defaultColumn option
   },
   useFilters,
   useGlobalFilter,
   useSortBy
 );

 return (
     <div>
       <table {...getTableProps()} style={{ border: 'solid 1px black' }}>
         <thead>
         {headerGroups.map(headerGroup => (
             <tr {...headerGroup.getHeaderGroupProps()}>
               {headerGroup.headers.map(column => (
                   <th
                       {...column.getHeaderProps(column.getSortByToggleProps())}
                       style={{
                         borderBottom: 'solid 3px red',
                         color: 'black',
                       }}
                   >
                     {column.render('Header')}
                     <span>
                       {column.isSorted
                           ? column.isSortedDesc
                               ? '🔽'
                               : '🔼'
                           : ''}
                    </span>
                    <div>{column.canFilter ? column.render('Filter') : null}</div>
                   </th>
               ))}
             </tr>
         ))}
         <tr>
           <th
             colSpan={visibleColumns.length}
             style={{
               textAlign: 'left',
             }}
           >
             <GlobalFilter
               preGlobalFilteredRows={preGlobalFilteredRows}
               globalFilter={state.globalFilter}
               setGlobalFilter={setGlobalFilter}
             />
           </th>
         </tr>
         </thead>
         <tbody {...getTableBodyProps()}>
         {rows.map(row => {
           prepareRow(row)
           return (
               <tr {...row.getRowProps()}>
                 {row.cells.map(cell => {
                   return (
                       <td
                           {...cell.getCellProps()}
                           style={{
                             padding: '10px',
                             border: 'solid 1px gray',
                           }}
                       >
                         {cell.render('Cell')}
                       </td>
                   )
                 })}
               </tr>
           )
         })}
         </tbody>
       </table>
     </div>
 );
}

export default Example;

Other react-table basic functions

React-table also allows you to implement basic table features such as pagination, row selection through checkboxes, column grouping, column ordering and even column drag and dropping using plugins already written. You just need to add the appropriate hook to your code. Api reference describes in great detail all the actions that you need to do to make your table work.

Best React Table Libraries and Examples

In this block, we will look at the best react table libraries and examples: today it is no longer effective to build and style tables manually, for there already is such a huge spectrum of fully prepared libraries available. We will present the pros and cons of each and point out the differences between them.

React-Table

react-table screenshot

React Table is one of the most popular table libraries in React. It has almost 15,000 stars on GitHub. The react-table library is very lightweight and offers all the basic features necessary for any simple table. Now, after the version 7 was released, it also supports Hooks. Moreover, the library is designed to have zero design, so you control the render and look of your table. The other great feature of React-table is a plugin ecosystem: if you want to extend the functionality of your grid, just add the necessary hook and that’s all.

Pros

  • Easy customization;
  • Headless approach;
  • Supports Pivoting and Aggregation;
  • Wide plugin ecosystem;
  • Lightweight (5kb – 14kb+ depending on features used).

Cons

  • In some cases the documentation is limited;
  • In our opinion, this table is not suitable for large data sets.

Notable features

  • Global search plugin;
  • Basic filtering and sorting options;
  • Custom sorting and filtering options for columns based on data types (numbers, string, boolean, select input, etc.);
  • Pagination support;
  • Ability to create custom plugin hooks.

Here’s a quick recap: react-table is good for simple tables that need basic features like searching, sorting, filtering, etc. Basic sports statistics, weather forecasts, basic finance data, user management table and others.

Bryntum grid

Bryntum grid screenshot

Bryntum Grid is a powerful & high-performance table component capable of handling 100k+ rows while still providing a great user experience. Bryntum Grid is developed on pure Javascript, so it’s framework agnostic. However, it comes with React wrappers to make integration into your project seamless. The main cons for this table is that it is not a pure react application, plus it’s a paid library. For that amount of money you want the pure react table component.

Features

  • Locked / frozen columns;
  • Cell editing; 
  • Custom cell rendering;
  • Dedicated support;
  • Paging Easily themeable with SASS.

Griddle

Griddle screenshot

Griddle is a customizable architecture React datagrid component. It ships with some basic conventions and functionality, but gives you the ability to customize just about anything (components, methods, etc). To encourage customization reuse, Griddle has plugin support. Plugins are packaged Griddle customizations that can be reused or shared. However, the library seems to be abandoned. The cons: seems that the support of this library is deprecated – the latest commit was in July 2019.

DevExtreme React DataGrid

React DataGrid screenshot

DevExtreme React Grid is a component that displays table data from a local or remote source. It supports pagination, sorting, filtering, grouping and other data generation options, row selection, and data editing. The support for managed and unattended state modes allows the Grid to be used in a regular or Redux-based application. The DevExtreme Grid component has a composable and extensible plugin-based architecture and also provides built-in Bootstrap and Material-UI rendering functionality and theme creation.

Notable features

  • Pure React;
  • Virtual scrolling;
  • Multi-column sorting and grouping;
  • Tree-view mode;
  • Custom UI Rendering.

Rsuite React Table

rsuite react table screenshot

This is a component of the React Table that supports virtualization, fixed columns and headers, tree views and more. The good thing about this library is that it comes with a lot of examples on each feature.

Pros

  • Library offers sorting, expandable child nodes, and RTL;
  • Detailed docs with many examples;
  • Many pre-built components inside.

Cons

  • Customizing this library might be a bit challenging;
  • There is no big community and active development of the library.

React Virtualized

react virtuilized screenshot

React-virtualized is a react table library heavily optimized for performance when the dataset is large. This library is not exactly a table library; it’s React components for efficiently rendering large lists and tabular data. You should consider using this product when you want to manage a large set of data. The documentation is comprehensive and the community around this tool is very mature, it has more than 18k stars on Github.

For normal use cases, this library would be overkill, and the API would be too advanced. You can successfully go with react-virtualized for custom timelines, charts involving infinitely long calendars, and heavy UI elements for your large dataset.

React Data grid

react data grid screenshot

React Data Grid is a react table library for creating apps similar to google spreadsheets and MS excel. The broad range of features includes data binding, editing, Excel-like filtering, custom sorting, row aggregation, Excel, CSV, and PDF format collection, and support.

Pros

  • Lightning-fast rendering;
  • Rich editing and formatting;
  • Configurable and customizable;
  • Packed with excel features including cell copy and paste.

Cons

  • Сomplicated to jumpstart with the development of the table;
  • Poor documentation;
  • It does not support pagination by default;
  • It is not easily customizable.

Key features

  • Excel-like filtering and grouping options;
  • Data exporting in any format: PDF, CSV, and Excel;
  • Inline editing of columns;
  • Supports virtual rendering for infinitely long table rows;
  • Uses Bootstrap for styling.

Kendo React Grid component

kendo ui react data grid screenshot

Kendo React Grid component is one of the most powerful data grid components available to React developers, containing many must-have features. React data table has a lot of complex features: reordering and resizing columns, displaying hierarchical data, column and context menus. These provide additional functionality based on currently selected rows or columns, options for custom rendering, and much, much more. Moreover, the Kendo React library is compliant with many security and accessibility standards out of the box.

Pros

  • Zero dependencies;
  • 100+ features to effectively manipulate the bit amount of data;
  • Documentation is very (!) well structured and comprehensive;
  • 3 themes of your choice;
  • Dedicated support team option.

Cons

  • Price is a bit high;
  • We assume that the implementation of custom styles can be a bit tricky.

If you want the table/grid to be a very comprehensive feature-packed component for your application, with good docs and dedicated support – we recommend looking at the Kendo UI React grid.

React data sheet

react data sheet screenshot

React-datasheet is similar to react-data-grid. It has many GitHub starts, so it’s well-maintained and has a very helpful and productive community. As you presumably noticed, the main goal of this library is to help you create your own Google Sheets/Excel-like application on React. The project has prebuilt styles and functions, so you will receive that view and complex functions out-of-the-box. However, note that this library is not suited for the basic, small-sized tables with limited functionality.

Pros

  • Well documented;
  • Good looking UI;
  • Good customization;
  • Pre Built formulas tables.

Cons

  • Limited to the specific use-case;
  • Not suitable for large datasets.

Material Table

material table react screenshot

Material table is one of the most popular react table libraries, thanks to material design and usage of Material-UI components. The project is very easy to use and install even for the beginners; robust documentation will speed up the development.

Pros

  • Feature-packed;
  • Pre build Export to CSV;
  • Robust documentation.

Cons

  • Component overriding;
  • Not everyone is a fan of Material UI.

How Material Table works

To start development you need to install this library by typing yarn add or npm install commands in the console. You also need to add Material-UI icons.

The library works in the following way – you just need to transfer two props to the <MaterialTable /> component. The prop data is there to display the data in row format. Another prop column defines the number of columns.

A third prop on <MaterialTable /> component called ‘title’ can be used to give a title to the whole table. See the example below:

return (
  <div>
    <MaterialTable columns={columns} data={data} title='Flatlogic' />
  </div>
);

By default, the material-table library displays a search bar and pagination. At Flatlogic we recommend to use Material table in case you are in love with Material-UI and material design.

RC-Table

RC-Table

Rc-Table is another useful tiny React Table library with the set of basic functions that will equip you to build a well structured react table. The table is good if you want to use your own styling. The other good thing with this library is that it is very easy to understand and start.

Pros

  • Very lightweight;
  • The docs has many examples with the source code;
  • Fast jump start to the actual development;
  • Limited community.

Cons

  • Documentation is not so good. Some functions are not described at all.

Thus this library is good for small applications or apps where the table is not a core part of the app.

Conclusion

As we saw from our guide, building react tables requires some effort compared to other libraries such as bootstrap. We also learned the fact that in most cases you do not need to develop your own react table from scratch: there already are many react table solutions for various project requirements, both paid and free.

When choosing a library for your requirements, pay attention to the number of stars on the github, how active the community is, how often the library is updated and how often the downloads happen.

However, let’s look at the cases when you can still consider building your own react table:

  • When you need a custom UI for the table. It might be faster to build your own;
  • When your table is just a showcase;
  • You need a very lightweight table without any dependencies.

We hope that our guide and selection were useful for you and that you have chosen the library that you will use when building the react table.

If you notice that our article is missing a good react table library, we will gladly consider including it in the collection – just drop us a line.

Ready-made React web application with Flatlogic React Templates

At Flatlogic we create web and mobile application templates including React templates to speed up the development process and drastically reduce the cost of the project. In our React templates, you can find many pre-built components including react tables with working basic functionality, like sorting and filtering. You can even get a fully working React CRUD application if you choose one of our react templates with Node.js, Java, or Laravel backend.

You might also like these articles