How to make tables sortable in React
Sortable tables enhance user experience by enabling dynamic data organization, especially crucial for dashboards and data-heavy applications. As the creator of CoreUI, a widely used open-source UI library, I’ve implemented sortable tables in countless enterprise React applications throughout my 11 years of frontend development. The most effective approach is managing sort state with useState and applying sort logic to reorder table data. This method provides responsive sorting with clear visual feedback and maintains clean component structure.
Manage sort column and direction in state, apply sorting logic to data array, and toggle sort on header clicks.
import { useState } from 'react'
const SortableTable = ({ data }) => {
const [sortConfig, setSortConfig] = useState({ key: null, direction: 'asc' })
const sortedData = [...data].sort((a, b) => {
if (!sortConfig.key) return 0
const aValue = a[sortConfig.key]
const bValue = b[sortConfig.key]
if (aValue < bValue) return sortConfig.direction === 'asc' ? -1 : 1
if (aValue > bValue) return sortConfig.direction === 'asc' ? 1 : -1
return 0
})
const handleSort = (key) => {
setSortConfig({
key,
direction: sortConfig.key === key && sortConfig.direction === 'asc' ? 'desc' : 'asc'
})
}
return (
<table>
<thead>
<tr>
<th onClick={() => handleSort('name')}>
Name {sortConfig.key === 'name' && (sortConfig.direction === 'asc' ? '↑' : '↓')}
</th>
<th onClick={() => handleSort('email')}>
Email {sortConfig.key === 'email' && (sortConfig.direction === 'asc' ? '↑' : '↓')}
</th>
<th onClick={() => handleSort('role')}>
Role {sortConfig.key === 'role' && (sortConfig.direction === 'asc' ? '↑' : '↓')}
</th>
</tr>
</thead>
<tbody>
{sortedData.map(user => (
<tr key={user.id}>
<td>{user.name}</td>
<td>{user.email}</td>
<td>{user.role}</td>
</tr>
))}
</tbody>
</table>
)
}
Here the sortConfig state tracks the currently sorted column key and direction. The sortedData creates a copy of the data array and sorts it based on the active column and direction. The handleSort function toggles between ascending and descending when clicking the same column, or resets to ascending for new columns. Arrow indicators (↑ ↓) provide visual feedback showing which column is sorted and in what direction. The sort comparison handles both string and numeric values correctly.
Best Practice Note:
This is the sorting approach we use in CoreUI table components for reliable data organization in enterprise dashboards. Use useMemo to optimize sorting performance for large datasets, implement multi-column sorting by tracking an array of sort configs, and consider case-insensitive sorting for string columns with toLowerCase() to improve user experience.



