loading

v33.4.0

select option

useSort hook

Build tables with sortable rows

The useSort hook

The NewTable API has behaviors like selecting and sorting extracted into hooks.

You can attach these hooks to your table to enhance the experience. We want to stress that the usage of these hooks is completely optional, you can create all of these behaviors on your own and by hand.

The objective is to cover the majority of the cases with the hooks and other APIs but still have the option of overwriting any default, creating flexibility.

How to use the useSort hook

This hook is used for front end sorting. This is not something we usually do at Carta, but for tables with a small number of rows, this hook can be handy as it's easy to use.

The hook receives your data Array and an optional config Object with the following type definition:

type ConfigObject = {
/* An initial state for the first render of the hook */
initialState?: {
/* A unique key for the table column */
key: string,
/* Set direction */
direction?: "ascending" | "descending",
},
/* Callback that's called after the sort function */
onSort?: (any) => void,
/* You can overwrite our internal sorting method by passing a custom one */
sort?: (any, sortConfig: { key: string, direction?: "ascending" | "descending" }) => Array<any>,
}

The hook returns your sorted data as a list of items. You should use the items array to build your table rows.

Basic usage

() => {
const data = [
{ id: "123", stakeholder: "Emily Wilson", email: "emily.wilson@carta.com", security: "ES-161" },
{ id: "234", stakeholder: "Tagg Palmer", email: "tagg.palmer@carta.com", security: "ES-262" },
{ id: "456", stakeholder: "Bruce Banner", email: "bruce.banner@avengers.com", security: "ES-456" },
];
const [sorted, actions] = useSort(data, { initialState: { key: "email", direction: "ascending" } });
return (
<NewTable data-testid="newtable-sortable">
<NewTable.Head>
<NewTable.Row>
<NewTable.HeadCell>
<NewTable.Pin {...actions.getPinProps("stakeholder")}>Stakeholder</NewTable.Pin>
</NewTable.HeadCell>
<NewTable.HeadCell>
<NewTable.Pin {...actions.getPinProps("email")}>Email</NewTable.Pin>
</NewTable.HeadCell>
<NewTable.HeadCell>
<NewTable.Pin
data-testid="newtable-sortable-pin"
onClick={() => actions.sort("security")}
direction={actions.getDirection("security")}
>
Security
</NewTable.Pin>
</NewTable.HeadCell>
</NewTable.Row>
</NewTable.Head>
<NewTable.Body>
{sorted.items.map((d) => (
<NewTable.Row key={d.id}>
<NewTable.Cell>{d.stakeholder}</NewTable.Cell>
<NewTable.Cell>{d.email}</NewTable.Cell>
<NewTable.Cell data-testid="newtable-sortable-cell">{d.security}</NewTable.Cell>
</NewTable.Row>
))}
</NewTable.Body>
</NewTable>
);
}

Custom sorting usage

() => {
const data = [
{ id: "234", stakeholder: "Tagg Palmer", email: "tagg.palmer@carta.com", security: "ES-262" },
{ id: "123", stakeholder: "Emily Wilson", email: "emily.wilson@carta.com", security: "ES-161" },
{ id: "456", stakeholder: "Bruce Banner", email: "bruce.banner@avengers.com", security: "ES-456" },
];
const [sorted, actions] = useSort(data, {
sort: (data, config) => {
// Custom sorting by surname
return data.sort((a, b) => {
if (a.stakeholder.split(" ")[1] < b.stakeholder.split(" ")[1]) {
return config.direction === "ascending" ? -1 : 1;
}
if (a.stakeholder.split(" ")[1] > b.stakeholder.split(" ")[1]) {
return config.direction === "ascending" ? 1 : -1;
}
return 0;
});
},
});
return (
<NewTable>
<NewTable.Head>
<NewTable.Row>
<NewTable.HeadCell>
<NewTable.Pin {...actions.getPinProps("stakeholder")}>Stakeholder</NewTable.Pin>
</NewTable.HeadCell>
<NewTable.HeadCell>Email</NewTable.HeadCell>
<NewTable.HeadCell>Security</NewTable.HeadCell>
</NewTable.Row>
</NewTable.Head>
<NewTable.Body>
{sorted.items.map((d) => (
<NewTable.Row key={d.id}>
<NewTable.Cell>{d.stakeholder}</NewTable.Cell>
<NewTable.Cell>{d.email}</NewTable.Cell>
<NewTable.Cell>{d.security}</NewTable.Cell>
</NewTable.Row>
))}
</NewTable.Body>
</NewTable>
);
}

Return types

// state
export type UseSortStateType = {
/* Array of sorted data */
items: Array<any>,
/* Sort configuration Object. `key` is the column key and `direction` the sort direction */
sortConfig: { key: string, direction: string },
}
// actions
export type UseSortActionsType = {
/* Sort callback. Receives the column `key` */
sort: (key: string) => void,
/* Based on a `key`, returns it's sort `direction` */
getDirection: (key: string) => string | undefined,
/* Helper function that returns the props that the NewTable.Pin needs to work with the hook.
* You can also pass this by hand as we did in the example above. */
getPinProps: (key: string) => {
onClick: (event: MouseEvent<HTMLSpanElement>) => void,
direction?: string,
},
/* Callback function to disable sorting */
disableSorting: () => void,
}

Is this page helpful?