Unlock the Power of Sortable Tables in React
Creating the Table Markup
We’ll start by creating a React project with Create React App and setting up the development server. Next, we’ll create the table markup, splitting it into different component files for better organization. We’ll have a Table
component as the parent, holding the TableHead
and TableBody
components.
// Table.js
import React from 'eact';
import TableHead from './TableHead';
import TableBody from './TableBody';
const Table = () => {
return (
<table>
<TableHead />
<TableBody />
</table>
);
};
export default Table;
Fetching and Rendering Table Data
Usually, we fetch table data from an API or backend server asynchronously. For this tutorial, we’ll generate some mock data from Mockaroo and store it in a JSON file. We’ll then import the data and store it in the state, passing it to the TableBody
component via props.
// data.json
[
{ id: 1, name: 'John Doe', age: 25 },
{ id: 2, name: 'Jane Doe', age: 30 },
//...
]
// Table.js
import React, { useState, useEffect } from 'eact';
import data from './data.json';
const Table = () => {
const [tableData, setTableData] = useState(data);
return (
<table>
<TableHead />
<TableBody data={tableData} />
</table>
);
};
Sorting the Table Data
To sort the table data, we’ll use the JavaScript sort()
function, which knows how to collate and order items. We’ll also use the localeCompare()
function to handle different data types, including strings, numbers, and dates.
const sortByColumn = (data, column, order) => {
return data.sort((a, b) => {
if (order === 'asc') {
return a[column].localeCompare(b[column]);
} else {
return b[column].localeCompare(a[column]);
}
});
};
Handling the onClick Event and Sorting Data
When we click a table header, we’ll keep track of the sort order and column using the useState
Hook. We’ll then define the logic to switch the order on every header click, updating the table data accordingly.
const TableHead = () => {
const [sortOrder, setSortOrder] = useState('asc');
const [sortedColumn, setSortedColumn] = useState(null);
const handleClick = (column) => {
if (sortedColumn === column) {
setSortOrder(sortOrder === 'asc'? 'desc' : 'asc');
} else {
setSortOrder('asc');
setSortedColumn(column);
}
// Update table data with new sort order
};
return (
<thead>
<tr>
{columns.map((column) => (
<th key={column} onClick={() => handleClick(column)}>
{column}
</th>
))}
</tr>
</thead>
);
};
Making the Table Reusable
To make the table reusable, we’ll extract the sorting logic into a custom Hook called useSortableTable
. This will enable us to reuse the sorting functionality in different table components.
const useSortableTable = (data, columns) => {
const [sortOrder, setSortOrder] = useState('asc');
const [sortedColumn, setSortedColumn] = useState(null);
const sortedData = sortByColumn(data, sortedColumn, sortOrder);
const handleHeaderClick = (column) => {
// Update sort order and sorted column
};
return { sortedData, handleHeaderClick };
};
Enabling or Disabling Sorting for Specific Columns
We’ll add a sortable
key to the columns items and specify a Boolean value to allow or disallow sorting for any column.
const columns = [
{ id: 'name', label: 'Name', sortable: true },
{ id: 'age', label: 'Age', sortable: false },
//...
];
Displaying Icons to Indicate Sorting Direction
We’ll dynamically add class names to the table header element to display arrow icons indicating the sorting direction.
<th className={`sortable ${sortedColumn === column? (sortOrder === 'asc'? 'asc' : 'desc') : ''}`} key={column} onClick={() => handleClick(column)}>
{column}
</th>
Implementing Editable Table Cells
To implement editable table cells, we’ll use the native input
element, rendering it in place of a table cell when clicked. We’ll then handle the state updates as typical in React.
const TableCell = ({ value, onChange }) => {
const [editing, setEditing] = useState(false);
const handleEdit = () => {
setEditing(true);
};
const handleSave = (newValue) => {
onChange(newValue);
setEditing(false);
};
return (
<td>
{editing? (
<input type="text" value={value} onChange={(e) => handleSave(e.target.value)} />
) : (
<span onClick={handleEdit}>{value}</span>
)}
</td>
);
};
Optimizing Performance for Large Datasets
Finally, we’ll cover some strategies for optimizing performance when rendering large datasets in React, including:
- Pagination
- Virtualization
- Memoization
- Server-side sorting
- Lazy loading
By following this tutorial, you’ll learn how to create a sortable table from scratch using React, reuse the table logic, and optimize performance for large datasets.