# useSorting

*Category:* Utilities
*Section:* Table & data hooks
*Source:* https://uikit.developers.rio.cloud/#/utilities/useSorting
*Captured:* 2026-04-27T14:59:48.464Z

The useSorting hook provides an easy way to sort any list by a specified key using natural sort order. It offers flexible control over sorting direction and key selection, making it ideal for dynamic sorting use cases.

## useSorting

### Example: Example 1

Name

Quantity

Box

20

Container

1

Crate

15

Drum

12

Pallet

10

Parcel

8

#### React (tsx)

```tsx
import Table, { TableBody, TableColumn, TableHeader, TableHeaderColumn, TableRow } from '@rio-cloud/rio-uikit/Table';
import useSorting from '@rio-cloud/rio-uikit/useSorting';

type Item = {
    name: string;
    quantity: number;
};

const items: Item[] = [
    { name: 'Pallet', quantity: 10 },
    { name: 'Container', quantity: 1 },
    { name: 'Crate', quantity: 15 },
    { name: 'Parcel', quantity: 8 },
    { name: 'Drum', quantity: 12 },
    { name: 'Box', quantity: 20 },
];

const UseSortingExample = () => {
    const { sortedItems, sortKey, sortDirection, setSortKey, setSortDirection } = useSorting(items, 'name');

    const handleSortChange = (columnKey: string, direction: 'asc' | 'desc') => {
        setSortKey(columnKey as keyof Item);
        setSortDirection(direction);
    };

    return (
        <Table rowKey='name' sortBy={String(sortKey)} sortDirection={sortDirection} onSortChange={handleSortChange}>
            <TableHeader>
                <TableHeaderColumn columnKey='name' sortable>
                    Name
                </TableHeaderColumn>
                <TableHeaderColumn columnKey='quantity' sortable>
                    Quantity
                </TableHeaderColumn>
            </TableHeader>
            <TableBody>
                {sortedItems.map(({ name, quantity }) => (
                    <TableRow key={name} id={name}>
                        <TableColumn columnKey='name'>{name}</TableColumn>
                        <TableColumn columnKey='quantity'>{quantity}</TableColumn>
                    </TableRow>
                ))}
            </TableBody>
        </Table>
    );
};

export default UseSortingExample;
```

#### HTML (html)

```html
<div class="table table-view-table border table-rounded table-has-head" role="table" style="--table-columns: minmax(50px, 1fr) minmax(50px, 1fr); --table-areas: &quot;table-col-1 table-col-2&quot;; --table-column-count: 2; --table-sticky-reference-top: var(--table-sticky-offset); --table-width: 908px;" aria-colcount="2">
    <div class="table-head" role="rowgroup">
        <div class="table-head-grid" role="row" style="grid-template-rows: repeat(1, auto);">
            <div class="table-head-cell table-head-cell-sortable table-head-cell-has-column-divider table-align-left table-vertical-align-middle" data-column="name" role="columnheader" aria-colindex="1" aria-rowindex="1" aria-sort="ascending" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-head-cell-content">
                    <div class="table-head-cell-content-row">
                        <button type="button" class="table-head-button">
                            <span class="table-head-button-label">
                                <span class="sort-arrows sort-asc">
                                </span>
                                <span class="table-head-label">Name</span>
                            </span>
                        </button>
                    </div>
                </div>
            </div>
            <div class="table-head-cell table-head-cell-sortable table-align-left table-vertical-align-middle" data-column="quantity" role="columnheader" aria-colindex="2" aria-rowindex="1" aria-sort="none" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-head-cell-content">
                    <div class="table-head-cell-content-row">
                        <button type="button" class="table-head-button">
                            <span class="table-head-button-label">
                                <span class="sort-arrows ">
                                </span>
                                <span class="table-head-label">Quantity</span>
                            </span>
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="table-body" role="rowgroup">
        <div id="Box" class="table-row" data-index="0" data-row-id="0" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Box</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">20</div>
            </div>
        </div>
        <div id="Container" class="table-row" data-index="1" data-row-id="1" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Container</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">1</div>
            </div>
        </div>
        <div id="Crate" class="table-row" data-index="2" data-row-id="2" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Crate</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">15</div>
            </div>
        </div>
        <div id="Drum" class="table-row" data-index="3" data-row-id="3" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Drum</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">12</div>
            </div>
        </div>
        <div id="Pallet" class="table-row" data-index="4" data-row-id="4" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Pallet</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">10</div>
            </div>
        </div>
        <div id="Parcel" class="table-row" data-index="5" data-row-id="5" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Parcel</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">8</div>
            </div>
        </div>
    </div>
</div>
```

#### Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| items | T[] | — | The array of items to be sorted. |
| initialKey | SortKey<T> = keyof T \| [keyof T, keyof T] | — | The initial key or keys to sort by. Must be a property of the items in the array. It can be either a single string or a tuple like ['name', 'date'] |
| initialDirection | SortDirectionType | SortDirection.ASCENDING | The initial sort direction. Can be SortDirection.ASCENDING or SortDirection.DESCENDING. |
| enableNaturalSort | boolean | true | Whether to use natural sort order. Defaults to false. |
| { sortedItems, sortKey, sortDirection, setSortKey, setSortDirection, toggleDirection } | Object | — | Returns an object containing: "sortedItems" - the sorted array "sortKey" - the key(s) to sort the data for "sortDirection" - the current direction that the data is sorted "setSortKey" - function to change the sorting key(s) afterwards "setSortDirection" - function to change the sorting order afterwards "toggleDirection" - function to toggle sort direction |

### Example: Example 2

Sort by a primary column. Hold shift key to sort by a secondary column
Category

Name

Quantity

Shipping

Parcel

8

Shipping

Box

20

Shipping

Envelope

50

Shipping

Bag

30

Storage

Pallet

10

Storage

Container

1

Storage

Crate

15

Storage

Drum

12

#### React (tsx)

```tsx
import Table, { TableBody, TableColumn, TableHeader, TableHeaderColumn, TableRow } from '@rio-cloud/rio-uikit/Table';
import useSorting from '@rio-cloud/rio-uikit/useSorting';

type Item = {
    name: string;
    category: string;
    quantity: number;
};

const items: Item[] = [
    { name: 'Pallet', category: 'Storage', quantity: 10 },
    { name: 'Container', category: 'Storage', quantity: 1 },
    { name: 'Crate', category: 'Storage', quantity: 15 },
    { name: 'Parcel', category: 'Shipping', quantity: 8 },
    { name: 'Drum', category: 'Storage', quantity: 12 },
    { name: 'Box', category: 'Shipping', quantity: 20 },
    { name: 'Envelope', category: 'Shipping', quantity: 50 },
    { name: 'Bag', category: 'Shipping', quantity: 30 },
];

const UseSortingSecondaryExample = () => {
    const { sortedItems, sortKey, sortDirection, setSortKey, setSortDirection, toggleDirection } = useSorting(
        items,
        'category'
    );

    const handleSortChange = (
        columnKey: string,
        direction: 'asc' | 'desc',
        event: React.MouseEvent<HTMLButtonElement>
    ) => {
        const column = columnKey as keyof Item;

        if (event.shiftKey) {
            if (Array.isArray(sortKey) && sortKey[1] === column) {
                toggleDirection();
            } else if (Array.isArray(sortKey)) {
                setSortKey([sortKey[0], column]);
                setSortDirection(direction);
            } else {
                setSortKey([sortKey, column]);
                setSortDirection(direction);
            }

            return;
        }

        if (Array.isArray(sortKey) ? sortKey[0] !== column : sortKey !== column) {
            setSortKey(column);
        }

        setSortDirection(direction);
    };

    return (
        <>
            <p>
                Sort by a primary column. Hold <kbd className='text-normal'>shift</kbd> key to sort by a secondary
                column
            </p>
            <Table
                rowKey='name'
                sortBy={Array.isArray(sortKey) ? sortKey.map(String) : String(sortKey)}
                sortDirection={sortDirection}
                onSortChange={handleSortChange}
            >
                <TableHeader>
                    <TableHeaderColumn columnKey='category' sortable>
                        Category
                    </TableHeaderColumn>
                    <TableHeaderColumn columnKey='name' sortable>
                        Name
                    </TableHeaderColumn>
                    <TableHeaderColumn columnKey='quantity' sortable>
                        Quantity
                    </TableHeaderColumn>
                </TableHeader>
                <TableBody>
                    {sortedItems.map(item => (
                        <TableRow key={item.name} id={item.name}>
                            <TableColumn columnKey='category'>{item.category}</TableColumn>
                            <TableColumn columnKey='name'>{item.name}</TableColumn>
                            <TableColumn columnKey='quantity'>{item.quantity}</TableColumn>
                        </TableRow>
                    ))}
                </TableBody>
            </Table>
        </>
    );
};

export default UseSortingSecondaryExample;
```

#### HTML (html)

```html
<p>Sort by a primary column. Hold <kbd class="text-normal">shift</kbd> key to sort by a secondary column</p>
<div class="table table-view-table border table-rounded table-has-head" role="table" style="--table-columns: minmax(50px, 1fr) minmax(50px, 1fr) minmax(50px, 1fr); --table-areas: &quot;table-col-1 table-col-2 table-col-3&quot;; --table-column-count: 3; --table-sticky-reference-top: var(--table-sticky-offset); --table-width: 908px;" aria-colcount="3">
    <div class="table-head" role="rowgroup">
        <div class="table-head-grid" role="row" style="grid-template-rows: repeat(1, auto);">
            <div class="table-head-cell table-head-cell-sortable table-head-cell-has-column-divider table-align-left table-vertical-align-middle" data-column="category" role="columnheader" aria-colindex="1" aria-rowindex="1" aria-sort="ascending" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-head-cell-content">
                    <div class="table-head-cell-content-row">
                        <button type="button" class="table-head-button">
                            <span class="table-head-button-label">
                                <span class="sort-arrows sort-asc">
                                </span>
                                <span class="table-head-label">Category</span>
                            </span>
                        </button>
                    </div>
                </div>
            </div>
            <div class="table-head-cell table-head-cell-sortable table-head-cell-has-column-divider table-align-left table-vertical-align-middle" data-column="name" role="columnheader" aria-colindex="2" aria-rowindex="1" aria-sort="none" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-head-cell-content">
                    <div class="table-head-cell-content-row">
                        <button type="button" class="table-head-button">
                            <span class="table-head-button-label">
                                <span class="sort-arrows ">
                                </span>
                                <span class="table-head-label">Name</span>
                            </span>
                        </button>
                    </div>
                </div>
            </div>
            <div class="table-head-cell table-head-cell-sortable table-align-left table-vertical-align-middle" data-column="quantity" role="columnheader" aria-colindex="3" aria-rowindex="1" aria-sort="none" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-head-cell-content">
                    <div class="table-head-cell-content-row">
                        <button type="button" class="table-head-button">
                            <span class="table-head-button-label">
                                <span class="sort-arrows ">
                                </span>
                                <span class="table-head-label">Quantity</span>
                            </span>
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="table-body" role="rowgroup">
        <div id="Parcel" class="table-row" data-index="0" data-row-id="0" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="category" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Shipping</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Parcel</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="3" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">8</div>
            </div>
        </div>
        <div id="Box" class="table-row" data-index="1" data-row-id="1" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="category" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Shipping</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Box</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="3" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">20</div>
            </div>
        </div>
        <div id="Envelope" class="table-row" data-index="2" data-row-id="2" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="category" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Shipping</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Envelope</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="3" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">50</div>
            </div>
        </div>
        <div id="Bag" class="table-row" data-index="3" data-row-id="3" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="category" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Shipping</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Bag</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="3" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">30</div>
            </div>
        </div>
        <div id="Pallet" class="table-row" data-index="4" data-row-id="4" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="category" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Storage</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Pallet</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="3" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">10</div>
            </div>
        </div>
        <div id="Container" class="table-row" data-index="5" data-row-id="5" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="category" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Storage</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Container</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="3" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">1</div>
            </div>
        </div>
        <div id="Crate" class="table-row" data-index="6" data-row-id="6" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="category" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Storage</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Crate</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="3" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">15</div>
            </div>
        </div>
        <div id="Drum" class="table-row" data-index="7" data-row-id="7" role="row">
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="category" role="cell" aria-colindex="1" style="grid-area: 1 / 1 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Storage</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="name" role="cell" aria-colindex="2" style="grid-area: 1 / 2 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">Drum</div>
            </div>
            <div class="table-cell table-align-left table-vertical-align-middle" data-column="quantity" role="cell" aria-colindex="3" style="grid-area: 1 / 3 / span 1 / span 1;">
                <div class="table-cell-content overflow-hidden">12</div>
            </div>
        </div>
    </div>
</div>
```

#### Props

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| items | T[] | — | The array of items to be sorted. |
| initialKey | SortKey<T> = keyof T \| [keyof T, keyof T] | — | The initial key or keys to sort by. Must be a property of the items in the array. It can be either a single string or a tuple like ['name', 'date'] |
| initialDirection | SortDirectionType | SortDirection.ASCENDING | The initial sort direction. Can be SortDirection.ASCENDING or SortDirection.DESCENDING. |
| enableNaturalSort | boolean | true | Whether to use natural sort order. Defaults to false. |
| { sortedItems, sortKey, sortDirection, setSortKey, setSortDirection, toggleDirection } | Object | — | Returns an object containing: "sortedItems" - the sorted array "sortKey" - the key(s) to sort the data for "sortDirection" - the current direction that the data is sorted "setSortKey" - function to change the sorting key(s) afterwards "setSortDirection" - function to change the sorting order afterwards "toggleDirection" - function to toggle sort direction |