In this tutorial, we are going to learn in easy ways how to build data tables in React web application from scratch using react-table package.
If you are beginner, then i will recommend going through following tutorials to get started with react:
Data table is very useful UI component, It helps in managing the complex set of data in any web or mobile application. A user can easily visualize, compare, sort, filter and scan information using a data table.
React 16+ Table Tutorial with Example
We are going to use react-table package to create a data table in React. We will learn to implement essential features of react-table library that helps to show the data in an organized way.
The react-table package is widely used data table third party package for 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.
Setting up React Project
Run the following command to install React app using create-react-app.
npx create-react-app react-table-tutorial
Start the app using below command:
npm start
You can view your app on: localhost:3000
Install react-table in React App
We are going to use the react-table plugin to build the data table component in our React app.
Install React Table, run either of the command based on your package manager:
# NPM
$ npm install react-table
# Yarn
$ yarn add react-table
We also need to install the styled-components using the following command:
styled-components
Build Data Table in React with react-table
Once we are done installing react-table in our React table application. Then we need to import the useTable API at the top of the src/App.js component.
import {useTable} from 'react-table';
Next, import the styled-component package, It allows you to write actual CSS code to style your React or React Native components.
npm i styled-components
Add the 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
Next, we will define the Table method and pass columns, data value into it. This method helps in rendering the data table UI, we have also declared the state and methods returned via useTable 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: '[email protected]',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: '[email protected]',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: '[email protected]',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: '[email protected]',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: '[email protected]',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: '[email protected]',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: '[email protected]',
age: 44,
status: 'Active'
},
{
name: 'Maxime_Nienow',
email: '[email protected]',
age: 26,
status: 'Active'
},
{
name: 'Glenna Reichert',
email: '[email protected]',
age: 30,
status: 'Inactive'
},
]
We must define the column directive and ad the column data, add the following code in the App.js file.
The ReactTable will render the data array by mapping the JSON data key associated with column accessor value. For example, our column 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>
)
Above code will successfully display the rows of data along with the data values as column header.
Here is 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: '[email protected]',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: '[email protected]',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: '[email protected]',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: '[email protected]',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: '[email protected]',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: '[email protected]',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: '[email protected]',
age: 44,
status: 'Active'
},
{
name: 'Maxime_Nienow',
email: '[email protected]',
age: 26,
status: 'Active'
},
{
name: 'Glenna Reichert',
email: '[email protected]',
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 Example
Tables allow you to gather a large amount of information and display that data in a more organized way. The react-table package is highly scalable and responsive, and It offers you pagination feature to manage the significant amount of data efficiently.
You can manage the large amount of data with usePagination API. Place the following code in the src/App.js file to enable the pagination in React table.
React Table pagination needs to have usePagination imported along with useTable API. We 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.
Create Responsive Table in React
Now, we are going to learn how to create React Responsive Table 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.
Here is the code for full-width responsive data table example in React:
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: '[email protected]',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: '[email protected]',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: '[email protected]',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: '[email protected]',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: '[email protected]',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: '[email protected]',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: '[email protected]',
age: 44,
status: 'Active'
},
{
name: 'Maxime_Nienow',
email: '[email protected]',
age: 26,
status: 'Active'
},
{
name: 'Glenna Reichert',
email: '[email protected]',
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
Create Responsive Table in React
Now, we are going to learn how to create React Responsive Table 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.
Here 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: '[email protected]',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: '[email protected]',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: '[email protected]',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: '[email protected]',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: '[email protected]',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: '[email protected]',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: '[email protected]',
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
Create React Data Table Sorting
Sorting is a way of arranging the data in ascending or descending order, and It helps to sort the 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.
Here 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: '[email protected]',
age: 28,
status: 'Active'
},
{
name: 'Ervin Howell',
email: '[email protected]',
age: 35,
status: 'Active'
},
{
name: 'Clementine Bauch',
email: '[email protected]',
age: 33,
status: 'Inactive'
},
{
name: 'Patricia Lebsack',
email: '[email protected]',
age: 25,
status: 'Active'
},
{
name: 'Kamren',
email: '[email protected]',
age: 42,
status: 'Active'
},
{
name: 'Dennis Schulist',
email: '[email protected]',
age: 34,
status: 'Inactive'
},
{
name: 'Kurtis Weissnat',
email: '[email protected]',
age: 44,
status: 'Active'
},
{
name: 'Maxime_Nienow',
email: '[email protected]',
age: 26,
status: 'Active'
},
{
name: 'Glenna Reichert',
email: '[email protected]',
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
i hope you like this articlle.