I had quite a bit of trouble figuring this one out as well. Here's how I did it. It's in typescript, but if you need it in plain js, just remove all the typings. 1st, here' the custom sort. It will sort strings, and always put the nulls/blanks/undefined at the end.
const customStringSort: any = (rowA: Row, rowB: Row, columnId: string, desc: boolean) => {
const defaultVal = desc ? 'AAAAAAAAAAAA' : 'ZZZZZZZZ';
return (rowA.values[columnId] ?? defaultVal)
.localeCompare(rowB.values[columnId] ?? defaultVal);
};
There are 2 things to notice about this.
- I couldn't figure out why typescript didn't like it when the return was defined as a number. I hate to use any, but this works.
- The react table documentation indicates that this must be memoized. This is not, but it works still.
Next you have to add this function to the sortTypes.
const sortTypes: Record<string, SortByFn<SomeObject>> = {
customStringSort: customStringSort,
};
Next, add the sortTypes to the useTable instance.
const {
getTableProps,
getTableBodyProps
headerGroups,
rows,
prepareRow,
} = useTable(
{
columns,
data,
sortTypes
},
useSortBy
);
Now you can add the custom function into your column definitions.
const columns: Column<SomeObject>[] = React.useMemo(() =>
[
{ accessor: 'someColumnID', Header: 'Some Column', sortType:'customStringSort' },
],
[],
);
Hope this helps!
--Edit: If you want to memoized the function, this works. Just replace customStringSort with customStringSortMemo where appropriate.
const customStringSort: any = React.useCallback((rowA: Row, rowB: Row, columnId: string, desc: boolean) =>
{
const defaultVal = desc ? 'AAAAAAAAAAAA' : 'ZZZZZZZZ';
return (rowA.values[columnId] ?? defaultVal).localeCompare(rowB.values[columnId] ?? defaultVal);
},
[]);
const customStringSortMemo = React.useMemo(() => customStringSort[customStringSort]);