or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

built-in-types.mdcolumn-management.mdcore-table.mdfiltering.mdgrouping.mdindex.mdlayout.mdpagination.mdrow-features.mdsorting.mdutilities.md

sorting.mddocs/

0

# Data Sorting

1

2

React Table provides comprehensive sorting capabilities including single-column sorting, multi-column sorting, and customizable sort types. The sorting system supports various data types and allows for complete customization of sorting behavior.

3

4

## Capabilities

5

6

### Column Sorting (useSortBy)

7

8

Enables single and multi-column sorting with customizable sort algorithms and intuitive user interactions.

9

10

```javascript { .api }

11

/**

12

* Adds sorting capabilities to the table

13

* @param hooks - Hook registration object

14

*/

15

function useSortBy(hooks: Hooks): void;

16

17

interface SortByInstance {

18

/** Set the complete sort configuration */

19

setSortBy: (sortBy: SortingRule[]) => void;

20

/** Toggle sorting for a specific column */

21

toggleSortBy: (columnId: string, desc?: boolean, multi?: boolean) => void;

22

/** Clear all sorting */

23

resetSortBy: () => void;

24

/** Rows before sorting was applied */

25

preSortedRows: Row[];

26

/** Rows after sorting */

27

sortedRows: Row[];

28

}

29

30

interface SortByColumnInstance {

31

/** Whether this column can be sorted */

32

canSort: boolean;

33

/** Whether this column is currently sorted */

34

isSorted: boolean;

35

/** Sort direction (true = descending, false = ascending) */

36

isSortedDesc?: boolean;

37

/** Position in multi-sort order (0-based) */

38

sortedIndex?: number;

39

/** Toggle sorting for this column */

40

toggleSortBy: (desc?: boolean, multi?: boolean) => void;

41

/** Clear sorting for this column */

42

clearSortBy: () => void;

43

/** Get props for sort toggle UI element */

44

getSortByToggleProps: PropGetter;

45

}

46

47

interface SortingRule {

48

/** Column ID to sort by */

49

id: string;

50

/** Sort direction (true = descending, false = ascending) */

51

desc: boolean;

52

}

53

```

54

55

**Configuration Options:**

56

57

```javascript { .api }

58

interface SortByOptions {

59

/** Disable automatic sorting (handle sorting externally) */

60

manualSortBy?: boolean;

61

/** Disable all sorting */

62

disableSortBy?: boolean;

63

/** Disable multi-column sorting */

64

disableMultiSort?: boolean;

65

/** Function to detect multi-sort events (default: shift key) */

66

isMultiSortEvent?: (event: Event) => boolean;

67

/** Maximum number of columns that can be sorted simultaneously */

68

maxMultiSortColCount?: number;

69

/** Disable removal of sorting when clicking a sorted column */

70

disableSortRemove?: boolean;

71

/** Disable removal in multi-sort mode */

72

disableMultiRemove?: boolean;

73

/** Custom sorting function */

74

orderByFn?: (rows: Row[], sortBy: SortingRule[], sortTypes: SortTypes) => Row[];

75

/** Custom sort type definitions */

76

sortTypes?: Record<string, SortFunction>;

77

/** Auto-reset sorting when data changes */

78

autoResetSortBy?: boolean;

79

/** Initial sort state */

80

initialState?: {

81

sortBy?: SortingRule[];

82

};

83

}

84

85

interface SortFunction {

86

(rowA: Row, rowB: Row, columnId: string, desc: boolean): number;

87

}

88

```

89

90

**Usage Example:**

91

92

```javascript

93

import React from 'react';

94

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

95

96

function SortableTable({ columns, data }) {

97

const {

98

getTableProps,

99

getTableBodyProps,

100

headerGroups,

101

rows,

102

prepareRow,

103

state: { sortBy },

104

} = useTable(

105

{

106

columns,

107

data,

108

initialState: {

109

sortBy: [

110

{ id: 'name', desc: false }, // Sort by name ascending initially

111

],

112

},

113

},

114

useSortBy

115

);

116

117

return (

118

<div>

119

{/* Sort Status Display */}

120

<div>

121

{sortBy.length > 0 && (

122

<div>

123

Sorted by: {sortBy.map((sort, index) => (

124

<span key={sort.id}>

125

{index > 0 && ', '}

126

{sort.id} ({sort.desc ? 'desc' : 'asc'})

127

</span>

128

))}

129

</div>

130

)}

131

</div>

132

133

<table {...getTableProps()}>

134

<thead>

135

{headerGroups.map(headerGroup => (

136

<tr {...headerGroup.getHeaderGroupProps()}>

137

{headerGroup.headers.map(column => (

138

<th {...column.getHeaderProps(column.getSortByToggleProps())}>

139

{column.render('Header')}

140

{/* Sort indicator */}

141

<span>

142

{column.isSorted ? (

143

column.isSortedDesc ? (

144

' ↓'

145

) : (

146

' ↑'

147

)

148

) : (

149

column.canSort ? ' ↕' : ''

150

)}

151

</span>

152

{/* Multi-sort index */}

153

{column.isSorted && sortBy.length > 1 && (

154

<span>{column.sortedIndex + 1}</span>

155

)}

156

</th>

157

))}

158

</tr>

159

))}

160

</thead>

161

<tbody {...getTableBodyProps()}>

162

{rows.map(row => {

163

prepareRow(row);

164

return (

165

<tr {...row.getRowProps()}>

166

{row.cells.map(cell => (

167

<td {...cell.getCellProps()}>

168

{cell.render('Cell')}

169

</td>

170

))}

171

</tr>

172

);

173

})}

174

</tbody>

175

</table>

176

</div>

177

);

178

}

179

```

180

181

### Built-in Sort Types

182

183

React Table includes several built-in sort functions for different data types.

184

185

```javascript { .api }

186

interface SortTypes {

187

/** Mixed alphanumeric sorting (default) */

188

alphanumeric: SortFunction;

189

/** Date/time sorting */

190

datetime: SortFunction;

191

/** Basic comparison sorting */

192

basic: SortFunction;

193

/** String sorting with case handling */

194

string: SortFunction;

195

/** Numeric sorting with string cleaning */

196

number: SortFunction;

197

}

198

```

199

200

**Sort Type Examples:**

201

202

```javascript

203

const columns = [

204

{

205

Header: 'Product Name',

206

accessor: 'name',

207

sortType: 'string', // Case-insensitive string sort

208

},

209

{

210

Header: 'Price',

211

accessor: 'price',

212

sortType: 'number', // Numeric sort (strips non-numeric characters)

213

},

214

{

215

Header: 'Created Date',

216

accessor: 'createdAt',

217

sortType: 'datetime', // Date sorting

218

Cell: ({ value }) => new Date(value).toLocaleDateString(),

219

},

220

{

221

Header: 'Product Code',

222

accessor: 'code',

223

sortType: 'alphanumeric', // Mixed text/number sort

224

},

225

{

226

Header: 'Status',

227

accessor: 'status',

228

sortType: 'basic', // Simple comparison

229

},

230

];

231

```

232

233

### Multi-Column Sorting

234

235

Enable sorting by multiple columns simultaneously with intuitive user interactions.

236

237

```javascript

238

function MultiSortTable({ columns, data }) {

239

const {

240

getTableProps,

241

getTableBodyProps,

242

headerGroups,

243

rows,

244

prepareRow,

245

state: { sortBy },

246

} = useTable(

247

{

248

columns,

249

data,

250

// Multi-sort configuration

251

disableMultiSort: false,

252

maxMultiSortColCount: 3, // Limit to 3 columns

253

isMultiSortEvent: (e) => e.shiftKey, // Use Shift+click for multi-sort

254

},

255

useSortBy

256

);

257

258

return (

259

<div>

260

<div>

261

<small>

262

Hold Shift and click column headers to sort by multiple columns.

263

{sortBy.length > 1 && ` Currently sorting by ${sortBy.length} columns.`}

264

</small>

265

</div>

266

267

<table {...getTableProps()}>

268

<thead>

269

{headerGroups.map(headerGroup => (

270

<tr {...headerGroup.getHeaderGroupProps()}>

271

{headerGroup.headers.map(column => (

272

<th {...column.getHeaderProps(column.getSortByToggleProps())}>

273

<div>

274

{column.render('Header')}

275

{column.isSorted && (

276

<span>

277

{column.isSortedDesc ? ' ↓' : ' ↑'}

278

{sortBy.length > 1 && (

279

<sup>{column.sortedIndex + 1}</sup>

280

)}

281

</span>

282

)}

283

</div>

284

</th>

285

))}

286

</tr>

287

))}

288

</thead>

289

<tbody {...getTableBodyProps()}>

290

{rows.map(row => {

291

prepareRow(row);

292

return (

293

<tr {...row.getRowProps()}>

294

{row.cells.map(cell => (

295

<td {...cell.getCellProps()}>

296

{cell.render('Cell')}

297

</td>

298

))}

299

</tr>

300

);

301

})}

302

</tbody>

303

</table>

304

</div>

305

);

306

}

307

```

308

309

### Custom Sort Functions

310

311

Create custom sorting logic for specialized data types or business requirements.

312

313

```javascript { .api }

314

/**

315

* Custom sort function signature

316

* @param rowA - First row to compare

317

* @param rowB - Second row to compare

318

* @param columnId - ID of the column being sorted

319

* @param desc - Whether sorting in descending order

320

* @returns Comparison result (-1, 0, 1)

321

*/

322

interface CustomSortFunction {

323

(rowA: Row, rowB: Row, columnId: string, desc: boolean): number;

324

}

325

```

326

327

**Custom Sort Examples:**

328

329

```javascript

330

// Custom sort for semantic versions

331

const semverSort = (rowA, rowB, columnId) => {

332

const a = rowA.values[columnId];

333

const b = rowB.values[columnId];

334

335

const aParts = a.split('.').map(Number);

336

const bParts = b.split('.').map(Number);

337

338

for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {

339

const aPart = aParts[i] || 0;

340

const bPart = bParts[i] || 0;

341

342

if (aPart < bPart) return -1;

343

if (aPart > bPart) return 1;

344

}

345

346

return 0;

347

};

348

349

// Custom sort for priority levels

350

const prioritySort = (rowA, rowB, columnId) => {

351

const priorityOrder = { 'Low': 1, 'Medium': 2, 'High': 3, 'Critical': 4 };

352

const a = priorityOrder[rowA.values[columnId]] || 0;

353

const b = priorityOrder[rowB.values[columnId]] || 0;

354

355

return a < b ? -1 : a > b ? 1 : 0;

356

};

357

358

// Custom sort for file sizes

359

const fileSizeSort = (rowA, rowB, columnId) => {

360

const parseSize = (size) => {

361

const units = { 'B': 1, 'KB': 1024, 'MB': 1024**2, 'GB': 1024**3 };

362

const match = size.match(/^(\d+(?:\.\d+)?)\s*([A-Z]+)$/i);

363

if (!match) return 0;

364

return parseFloat(match[1]) * (units[match[2].toUpperCase()] || 1);

365

};

366

367

const a = parseSize(rowA.values[columnId]);

368

const b = parseSize(rowB.values[columnId]);

369

370

return a < b ? -1 : a > b ? 1 : 0;

371

};

372

373

// Register custom sort types

374

const table = useTable(

375

{

376

columns,

377

data,

378

sortTypes: {

379

semver: semverSort,

380

priority: prioritySort,

381

fileSize: fileSizeSort,

382

},

383

},

384

useSortBy

385

);

386

```

387

388

### Column Sort Configuration

389

390

Configure sorting behavior at the column level.

391

392

```javascript { .api }

393

interface ColumnSortConfig {

394

/** Sort type name or custom sort function */

395

sortType?: string | SortFunction;

396

/** Whether this column can be sorted */

397

disableSortBy?: boolean;

398

/** Whether to sort descending first (instead of ascending) */

399

sortDescFirst?: boolean;

400

/** Sort method for this specific column */

401

sortMethod?: SortFunction;

402

}

403

```

404

405

**Column Sort Examples:**

406

407

```javascript

408

const columns = [

409

{

410

Header: 'Name',

411

accessor: 'name',

412

sortType: 'string',

413

sortDescFirst: false, // Sort A-Z first, then Z-A

414

},

415

{

416

Header: 'Created Date',

417

accessor: 'createdAt',

418

sortType: 'datetime',

419

sortDescFirst: true, // Sort newest first by default

420

},

421

{

422

Header: 'File Size',

423

accessor: 'size',

424

sortType: 'fileSize', // Custom sort type

425

},

426

{

427

Header: 'Actions',

428

id: 'actions',

429

disableSortBy: true, // Not sortable

430

Cell: ({ row }) => <button>Edit</button>,

431

},

432

{

433

Header: 'Score',

434

accessor: 'score',

435

// Inline custom sort function

436

sortType: (rowA, rowB, columnId) => {

437

const a = rowA.values[columnId];

438

const b = rowB.values[columnId];

439

440

// Handle null/undefined scores

441

if (a == null) return b == null ? 0 : -1;

442

if (b == null) return 1;

443

444

return a < b ? -1 : a > b ? 1 : 0;

445

},

446

},

447

];

448

```

449

450

### Manual Sorting

451

452

Take control of sorting logic for server-side or custom implementations.

453

454

```javascript

455

function ManualSortTable({ columns, data }) {

456

const [sortBy, setSortBy] = React.useState([

457

{ id: 'name', desc: false }

458

]);

459

460

// Fetch sorted data based on current sort configuration

461

const sortedData = React.useMemo(() => {

462

return fetchSortedData(data, sortBy);

463

}, [data, sortBy]);

464

465

const {

466

getTableProps,

467

getTableBodyProps,

468

headerGroups,

469

rows,

470

prepareRow,

471

} = useTable(

472

{

473

columns,

474

data: sortedData,

475

manualSortBy: true, // Disable automatic sorting

476

// Provide current sort state

477

state: {

478

sortBy,

479

},

480

// Handle sort changes

481

onSortByChange: setSortBy,

482

},

483

useSortBy

484

);

485

486

return (

487

<div>

488

<div>

489

Server-side sorting: {sortBy.map(sort =>

490

`${sort.id} ${sort.desc ? 'desc' : 'asc'}`

491

).join(', ')}

492

</div>

493

494

<table {...getTableProps()}>

495

{/* Table implementation */}

496

</table>

497

</div>

498

);

499

}

500

```

501

502

### Advanced Sorting Features

503

504

Additional sorting utilities and methods for complex scenarios.

505

506

```javascript { .api }

507

interface SortByUtilities {

508

/** Default multi-column sorting function */

509

defaultOrderByFn: (

510

rows: Row[],

511

sortBy: SortingRule[],

512

sortTypes: SortTypes

513

) => Row[];

514

}

515

```

516

517

**Custom Sorting Algorithm Example:**

518

519

```javascript

520

// Custom multi-column sort with null handling

521

const customOrderByFn = (rows, sortBy, sortTypes) => {

522

return rows.slice().sort((rowA, rowB) => {

523

for (let i = 0; i < sortBy.length; i++) {

524

const { id, desc } = sortBy[i];

525

const sortType = sortTypes[id] || sortTypes.alphanumeric;

526

527

let result = sortType(rowA, rowB, id, desc);

528

529

// Handle null/undefined values

530

const aValue = rowA.values[id];

531

const bValue = rowB.values[id];

532

533

if (aValue == null && bValue == null) {

534

result = 0;

535

} else if (aValue == null) {

536

result = desc ? 1 : -1; // Nulls last

537

} else if (bValue == null) {

538

result = desc ? -1 : 1; // Nulls last

539

}

540

541

if (result !== 0) {

542

return desc ? -result : result;

543

}

544

}

545

return 0;

546

});

547

};

548

549

const table = useTable(

550

{

551

columns,

552

data,

553

orderByFn: customOrderByFn,

554

},

555

useSortBy

556

);

557

```

558

559

### Sort Toggle Props

560

561

The `getSortByToggleProps` method provides attributes for interactive sort controls.

562

563

```javascript

564

// Basic usage with default click handler

565

<th {...column.getHeaderProps(column.getSortByToggleProps())}>

566

{column.render('Header')}

567

</th>

568

569

// Custom click handler while keeping sort functionality

570

<th {...column.getHeaderProps(column.getSortByToggleProps({

571

onClick: (e) => {

572

console.log('Sorting column:', column.id);

573

// Default sort handling will still occur

574

},

575

className: 'sortable-header',

576

style: { userSelect: 'none' }

577

}))}>

578

{column.render('Header')}

579

</th>

580

581

// Completely custom sort button

582

<th {...column.getHeaderProps()}>

583

{column.render('Header')}

584

{column.canSort && (

585

<button

586

onClick={() => column.toggleSortBy()}

587

className={column.isSorted ? 'sorted' : ''}

588

>

589

Sort {column.isSorted && (column.isSortedDesc ? '↓' : '↑')}

590

</button>

591

)}

592

</th>

593

```

594

595

## Types

596

597

```javascript { .api }

598

interface TableState {

599

/** Current sort configuration */

600

sortBy: SortingRule[];

601

}

602

603

interface SortingRule {

604

/** Column ID */

605

id: string;

606

/** Sort direction */

607

desc: boolean;

608

}

609

610

interface SortTypes {

611

[key: string]: SortFunction;

612

}

613

614

interface SortMeta {

615

instance: TableInstance;

616

column: Column;

617

}

618

```