Friends, in this tutorial we will learn how to build data tables in React Web applications from scratch. We will use the react-table package for doing so.
Even if you are a novice in creating React Applications, then also this guide will teach how to do it in a simple and easy way.
Using React-strap in React App
A Data Table is a very useful UI Component. It helps in managing the complex set of data in any web or mobile application. It becomes quite easy for the user to visualise, compare, sort, filter and scan information using a data table.
React 17 Table Tutorial With Example
In this guide, we will use react-table package to create a data table in react. We will also learn to implement essential features of react-table library that help in showing the data in an organised way.
The react-table package is a widely used data table third-party package from React framework. This library is extremely light and provides almost all the basic table features which are necessary to display the complex information to the users.
Now, let’s learn about some of the features:
- Filters
- Resizable
- Animatable
- Row Selection
- Row Expansion
- Virtualizable
- Column Ordering
- Pivoting and Aggregation
- Sorting (Multi and Stable)
- Server Side/Controlled Data/State
- Extensible via hook-based plugin system
- Auto out of the box, fully controllable API
- Headless (100 % customizable, Bring-your-own-UI)
- Lightweight (5 kb- 12 kb+ depending on features used and tree shaking)
Let’s Learn To Build React 17 Data Table With react-table Package
Step 1- Set Up The React Project
Since we know that the very basic step is to set up react project. So, we install React app using create-react-app by running the following command:
npx create-react-app react-data-table-example
Here, we start the app with below command:
npm start
Step 2- Install react-table In React App
Next, we have to react-table plugin to build the data table component in our React app.
Install react-table, then we run either of the command based on our package manager.
# NPM
$ npm install react-table
# Yarn
$ yarn add react-table
Step 3- Build Data Table In React With react-table
Further, we will import styled-component package, it allows us to write actual CSS style to code our React or React Native Components.
npm i styled-components
After we are done with installing react-table in our react application, then we have to import the useTable API at the top of the src/App.js component.
import {useTable} from 'react-table';
Add code in the App.js component to design our data table.
const Styles = styled.div `
table {
width: 100%;
border-spacing: 0;
border: 1px solid black;
tr {
:last-child {
td {
border-bottom: 0;
}
}
}
th,
td {
margin: 0;
padding: 1rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
:last-child {
border-right: 0;
}
}
}
`
Create Table UI
Here, we will define the Table method and pass columns, data value in it. This method helps in rendering the data table UI, we have also declared the state and methods returned via useTables API to create the data table component in React.
function Table({columns, data}) {
const {getTableProps, getTableBodyProps, headerGroups, rows, prepareRow} = useTable({columns, data})
// Render Data Table UI
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup
.headers
.map(column => (
<th {...column.getHeaderProps()}>{column.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>
)
}
We must have some data that will be rendered by the react-table package in the React data table component.
const data = [
{
name: 'Leanne Graham',
email: 'Sincere@april.biz',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: 'Shanna@melissa.tv',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: 'Nathan@yesenia.net',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: 'Julianne@kory.org',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: 'Hettinger@annie.ca',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: 'Dach@jasper.info',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: 'Hoeger@billy.biz',
age: 44,
status: 'Active'
},
{
name: 'Maxime_Nienow',
email: 'Sherwood@rosamond.me',
age: 26,
status: 'Active'
},
{
name: 'Glenna Reichert',
email: 'McDermott@dana.io',
age: 30,
status: 'Inactive'
},
]
We must define the column directive and add the column data, add the following code in App.js file.
The ReactTable will render the data array by mapping the JSON data key associated with column accessor value. For example, our common headers values in table are Name, Email, Age and Status.
const columns = [
{
Header: 'Name',
accessor: 'name'
}, {
Header: 'Email',
accessor: 'email'
}, {
Header: 'Age',
accessor: 'age'
}, {
Header: 'Status',
accessor: 'status'
}
]
Inside the return method, define the Styles attribute to style the Table UI, then set the Table attribute along with table properties to render the JSON data in the React table.
return (
<Styles>
<Table
data={data}
columns={columns}
/>
</Styles>
)
The above-mentioned code will display the rows of data along with the data values as the column header.
See below how the final App component looks in the src/App.js file:
import React from 'react';
import {useTable} from 'react-table'
import styled from 'styled-components'
const Styles = styled.div `
table {
width: 100%;
border-spacing: 0;
border: 1px solid black;
tr {
:last-child {
td {
border-bottom: 0;
}
}
}
th,
td {
margin: 0;
padding: 1rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
:last-child {
border-right: 0;
}
}
}
`
function Table({columns, data}) {
const {getTableProps, getTableBodyProps, headerGroups, rows, prepareRow} = useTable({columns, data})
// Render Data Table UI
return (
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup
.headers
.map(column => (
<th {...column.getHeaderProps()}>{column.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>
)
}
function App() {
const data = [
{
name: 'Leanne Graham',
email: 'Sincere@april.biz',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: 'Shanna@melissa.tv',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: 'Nathan@yesenia.net',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: 'Julianne@kory.org',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: 'Hettinger@annie.ca',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: 'Dach@jasper.info',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: 'Hoeger@billy.biz',
age: 44,
status: 'Active'
},
{
name: 'Maxime_Nienow',
email: 'Sherwood@rosamond.me',
age: 26,
status: 'Active'
},
{
name: 'Glenna Reichert',
email: 'McDermott@dana.io',
age: 30,
status: 'Inactive'
},
]
const columns = [
{
Header: 'Name',
accessor: 'name'
}, {
Header: 'Email',
accessor: 'email'
}, {
Header: 'Age',
accessor: 'age'
}, {
Header: 'Status',
accessor: 'status'
}
]
return (
<Styles>
<Table
data={data}
columns={columns}
/>
</Styles>
)
}
export default App
Step 4- React Table Pagination Example
The tables are used to gather a large amount of information and display it in a more organized manner. The react-table package is highly scalable and responsive, and it offers us a pagination feature to manage a significant amount of data efficiently.
We can manage a large amount of data with usePagination API. We simply need to place the below given code in the src/App.js file to enable pagination in react table.
import React from 'react';
import styled from 'styled-components'
import { useTable, usePagination } from 'react-table'
const Styles = styled.div `
table {
width: 100%;
border-spacing: 0;
border: 1px solid black;
tr {
:last-child {
td {
border-bottom: 0;
}
}
}
th,
td {
margin: 0;
padding: 1rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
:last-child {
border-right: 0;
}
}
}
`
function Table({columns, data}) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page, // Instead of using 'rows', we'll use page,
// which has only the rows for the active page
// The rest of these things are super handy, too ;)
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
initialState: { pageIndex: 0 },
},
usePagination
)
// Render Data Table UI
return (
<>
<table {...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>
{/* Pagination */}
<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>
</>
)
}
function App() {
const data = [
{
name: 'Leanne Graham',
email: 'Sincere@april.biz',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: 'Shanna@melissa.tv',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: 'Nathan@yesenia.net',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: 'Julianne@kory.org',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: 'Hettinger@annie.ca',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: 'Dach@jasper.info',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: 'Hoeger@billy.biz',
age: 44,
status: 'Active'
},
{
name: 'Maxime_Nienow',
email: 'Sherwood@rosamond.me',
age: 26,
status: 'Active'
},
{
name: 'Glenna Reichert',
email: 'McDermott@dana.io',
age: 30,
status: 'Inactive'
},
]
const columns = [
{
Header: 'Name',
accessor: 'name'
}, {
Header: 'Email',
accessor: 'email'
}, {
Header: 'Age',
accessor: 'age'
}, {
Header: 'Status',
accessor: 'status'
}
]
return (
<Styles>
<Table data={data} columns={columns}/>
</Styles>
)
}
export default App
React Table pagination needs to have usePagination imported along with useTable API. We have implemented the default pagination in React table that is highly customizable; you can edit and update the pagination values even the initial Table page index.
Step 5- Create Responsive Table In React
In this step, we will see how to create responsive table in React using useFlexLayout API, the react-table plugin offers useFlexLayout API and it allows making full width resizable data table that works flawlessly in every device.
Below-given is the code for full-width responsive data table example in react:
import React from 'react'
import styled from 'styled-components'
import {
useTable,
useResizeColumns,
useFlexLayout,
useRowSelect,
} from 'react-table'
const Styles = styled.div`
padding: 1rem;
.table {
${''}
display: block;
${''}
overflow: auto;
border-spacing: 0;
border: 1px solid black;
.thead {
${''}
overflow-y: auto;
overflow-x: hidden;
}
.tbody {
${''}
overflow-y: scroll;
overflow-x: hidden;
height: 250px;
}
.tr {
:last-child {
.td {
border-bottom: 0;
}
}
border-bottom: 1px solid black;
}
.th,
.td {
margin: 0;
padding: 0.5rem;
border-right: 1px solid black;
${''}
position: relative;
:last-child {
border-right: 0;
}
.resizer {
right: -5px;
background: blue;
width: 10px;
height: 100%;
position: absolute;
top: 0;
z-index: 1;
${''}
touch-action:none;
&.isResizing {
background: red;
}
}
}
.th {
&:last-of-type {
.resizer {
${''}
${''}
right: -15px;
}
}
}
}
`
const headerProps = (props, { column }) => getStyles(props, column.align)
const cellProps = (props, { cell }) => getStyles(props, cell.column.align)
const getStyles = (props, align = 'left') => [
props,
{
style: {
justifyContent: align === 'right' ? 'flex-end' : 'flex-start',
alignItems: 'flex-start',
display: 'flex',
},
},
]
function Table({ columns, data }) {
const defaultColumn = React.useMemo(
() => ({
minWidth: 30,
width: 150,
maxWidth: 200,
}),
[]
)
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable(
{
columns,
data,
defaultColumn,
},
useResizeColumns,
useFlexLayout,
useRowSelect,
hooks => {
}
)
return (
<div {...getTableProps()} className="table">
<div>
{headerGroups.map(headerGroup => (
<div
{...headerGroup.getHeaderGroupProps({
style: { paddingRight: '15px' },
})}
className="tr"
>
{headerGroup.headers.map(column => (
<div {...column.getHeaderProps(headerProps)} className="th">
{column.render('Header')}
{column.canResize && (
<div
{...column.getResizerProps()}
className={`resizer ${
column.isResizing ? 'isResizing' : ''
}`}
/>
)}
</div>
))}
</div>
))}
</div>
<div {...getTableBodyProps()} className="tbody">
{rows.map((row, i) => {
prepareRow(row)
return (
<div {...row.getRowProps()} className="tr">
{row.cells.map(cell => {
return (
<div {...cell.getCellProps(cellProps)} className="td">
{cell.render('Cell')}
</div>
)
})}
</div>
)
})}
</div>
</div>
)
}
function App() {
const data = [
{
name: 'Leanne Graham',
email: 'Sincere@april.biz',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: 'Shanna@melissa.tv',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: 'Nathan@yesenia.net',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: 'Julianne@kory.org',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: 'Hettinger@annie.ca',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: 'Dach@jasper.info',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: 'Hoeger@billy.biz',
age: 44,
status: 'Active'
}
]
const columns = [
{
Header: 'Name',
accessor: 'name'
}, {
Header: 'Email',
accessor: 'email'
}, {
Header: 'Age',
accessor: 'age'
}, {
Header: 'Status',
accessor: 'status'
}
]
return (
<Styles>
<Table columns={columns} data={data} />
</Styles>
)
}
export default App
Step 6- Create React Data Table Sorting
By sorting, we arrange the data in ascending or descending order, and it helps in sorting a large amount of data (numbers and words) in Table.
We are going to implement the Table sorting functionality in React app using the react-table’ useSortBy API package.
Below-given is the final code for React data table sorting feature:
import React from 'react'
import styled from 'styled-components'
import { useTable, useSortBy } from 'react-table'
const Styles = styled.div`
padding: 1rem;
table {
border-spacing: 0;
border: 1px solid black;
tr {
:last-child {
td {
border-bottom: 0;
}
}
}
th,
td {
margin: 0;
padding: 0.5rem;
border-bottom: 1px solid black;
border-right: 1px solid black;
:last-child {
border-right: 0;
}
}
}
`
function Table({ columns, data }) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable(
{
columns,
data,
},
useSortBy
)
// We don't want to render all 2000 rows for this example, so cap
// it at 20 for this use case
const firstPageRows = rows.slice(0, 20)
return (
<>
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
// Add the sorting props to control sorting. For this example
// we can add them into the header props
<th {...column.getHeaderProps(column.getSortByToggleProps())}>
{column.render('Header')}
{/* Add a sort direction indicator */}
<span>
{column.isSorted
? column.isSortedDesc
? ' 🔽'
: ' 🔼'
: ''}
</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{firstPageRows.map(
(row, i) => {
prepareRow(row);
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return (
<td {...cell.getCellProps()}>{cell.render('Cell')}</td>
)
})}
</tr>
)}
)}
</tbody>
</table>
</>
)
}
function App() {
const data = [
{
name: 'Leanne Graham',
email: 'Sincere@april.biz',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: 'Shanna@melissa.tv',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: 'Nathan@yesenia.net',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: 'Julianne@kory.org',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: 'Hettinger@annie.ca',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: 'Dach@jasper.info',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: 'Hoeger@billy.biz',
age: 44,
status: 'Active'
},
{
name: 'Maxime_Nienow',
email: 'Sherwood@rosamond.me',
age: 26,
status: 'Active'
},
{
name: 'Glenna Reichert',
email: 'McDermott@dana.io',
age: 30,
status: 'Inactive'
},
]
const columns = [
{
Header: 'Name',
accessor: 'name'
}, {
Header: 'Email',
accessor: 'email'
}, {
Header: 'Age',
accessor: 'age'
}, {
Header: 'Status',
accessor: 'status'
}
]
return (
<Styles>
<Table columns={columns} data={data} />
</Styles>
)
}
export default App
Conclusion
So, friends, we come to the conclusion. Hopefully, we have learnt the React Table tutorial. Throughout this guide, we have seen how to create react table using the react-table package.
We have also learnt how to display data in a beautiful way in React.
Thanks