I am trying to sort data using custom sort function in react. Unfortunately the function only sort items if the records are either capital letter or small letter. It doesn’t sort the data with mixed capital and small letter properly. Here is the live link
Here is the code
const useSortableData = (items, config = null) => {
const [sortConfig, setSortConfig] = React.useState(config);
const sortedItems = React.useMemo(() => {
let sortableItems = [...items];
if (sortConfig !== null) {
sortableItems.sort((a, b) => {
if (a[sortConfig.key] < b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? -1 : 1;
}
if (a[sortConfig.key] > b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? 1 : -1;
}
return 0;
});
}
return sortableItems;
}, [items, sortConfig]);
const requestSort = (key) => {
let direction = 'ascending';
if (
sortConfig &&
sortConfig.key === key &&
sortConfig.direction === 'ascending'
) {
direction = 'descending';
}
setSortConfig({ key, direction });
};
return { items: sortedItems, requestSort, sortConfig };
};
const ProductTable = (props) => {
const { items, requestSort, sortConfig } = useSortableData(props.products);
const getClassNamesFor = (name) => {
if (!sortConfig) {
return;
}
return sortConfig.key === name ? sortConfig.direction : undefined;
};
return (
<table>
<caption>Products</caption>
<thead>
<tr>
<th>
<button
type="button"
onClick={() => requestSort('name')}
className={getClassNamesFor('name')}
>
Name
</button>
</th>
<th>
<button
type="button"
onClick={() => requestSort('price')}
className={getClassNamesFor('price')}
>
Price
</button>
</th>
<th>
<button
type="button"
onClick={() => requestSort('stock')}
className={getClassNamesFor('stock')}
>
In Stock
</button>
</th>
</tr>
</thead>
<tbody>
{items.map((item) => (
<tr key={item.id}>
<td>{item.name}</td>
<td>${item.price}</td>
<td>{item.stock}</td>
</tr>
))}
</tbody>
</table>
);
};
function App() {
return (
<div className="App">
<ProductTable
products={[
{ id: 1, name: 'Cheese', price: 4.9, stock: 20 },
{ id: 2, name: 'milk', price: 1.9, stock: 32 },
{ id: 3, name: 'Yoghurt', price: 2.4, stock: 12 },
{ id: 4, name: 'Heavy Cream', price: 3.9, stock: 9 },
{ id: 5, name: 'butter', price: 0.9, stock: 99 },
{ id: 6, name: 'Sour Cream ', price: 2.9, stock: 86 },
{ id: 7, name: 'Fancy French Cheese š«š·', price: 99, stock: 12 },
]}
/>
</div>
);
}
ReactDOM.createRoot(document.querySelector("#root")).render(<App />);body {
font-family: 'open sans', sans-serif;
font-size: 16px;
}
table {
width: 100%;
border-collapse: collapse;
}
thead th {
text-align: left;
border-bottom: 2px solid black;
}
thead button {
border: 0;
border-radius: none;
font-family: inherit;
font-weight: 700;
font-size: inherit;
padding: 0.5em;
margin-bottom: 1px;
}
thead button.ascending::after {
content: 'š';
display: inline-block;
margin-left: 1em;
}
thead button.descending::after {
content: 'āļø';
display: inline-block;
margin-left: 1em;
}
tbody td {
padding: 0.5em;
border-bottom: 1px solid #ccc;
}
tbody tr:hover {
background-color: #eee;
}<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script> <div id="root"></div>
I have tried to change a and b to lowercase from useSortable but since there is price column with number, I got error.
What can I do to make it work regardless of case sensitivity.
Advertisement
Answer
You can check for the type, like:
if (typeof a[sortConfig.key] === "string" && typeof b[sortConfig.key] === "string") {
if (a[sortConfig.key].toLowerCase() < b[sortConfig.key].toLowerCase()) {
return sortConfig.direction === 'ascending' ? -1 : 1;
}
} else {
if (a[sortConfig.key] < b[sortConfig.key]) {
return sortConfig.direction === 'ascending' ? -1 : 1;
}
}