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
JavaScript
x
108
108
1
const useSortableData = (items, config = null) => {
2
const [sortConfig, setSortConfig] = React.useState(config);
3
4
const sortedItems = React.useMemo(() => {
5
let sortableItems = [items];
6
if (sortConfig !== null) {
7
sortableItems.sort((a, b) => {
8
if (a[sortConfig.key] < b[sortConfig.key]) {
9
return sortConfig.direction === 'ascending' ? -1 : 1;
10
}
11
if (a[sortConfig.key] > b[sortConfig.key]) {
12
return sortConfig.direction === 'ascending' ? 1 : -1;
13
}
14
return 0;
15
});
16
}
17
return sortableItems;
18
}, [items, sortConfig]);
19
20
const requestSort = (key) => {
21
let direction = 'ascending';
22
if (
23
sortConfig &&
24
sortConfig.key === key &&
25
sortConfig.direction === 'ascending'
26
) {
27
direction = 'descending';
28
}
29
setSortConfig({ key, direction });
30
};
31
32
return { items: sortedItems, requestSort, sortConfig };
33
};
34
35
const ProductTable = (props) => {
36
const { items, requestSort, sortConfig } = useSortableData(props.products);
37
const getClassNamesFor = (name) => {
38
if (!sortConfig) {
39
return;
40
}
41
return sortConfig.key === name ? sortConfig.direction : undefined;
42
};
43
return (
44
<table>
45
<caption>Products</caption>
46
<thead>
47
<tr>
48
<th>
49
<button
50
type="button"
51
onClick={() => requestSort('name')}
52
className={getClassNamesFor('name')}
53
>
54
Name
55
</button>
56
</th>
57
<th>
58
<button
59
type="button"
60
onClick={() => requestSort('price')}
61
className={getClassNamesFor('price')}
62
>
63
Price
64
</button>
65
</th>
66
<th>
67
<button
68
type="button"
69
onClick={() => requestSort('stock')}
70
className={getClassNamesFor('stock')}
71
>
72
In Stock
73
</button>
74
</th>
75
</tr>
76
</thead>
77
<tbody>
78
{items.map((item) => (
79
<tr key={item.id}>
80
<td>{item.name}</td>
81
<td>${item.price}</td>
82
<td>{item.stock}</td>
83
</tr>
84
))}
85
</tbody>
86
</table>
87
);
88
};
89
90
function App() {
91
return (
92
<div className="App">
93
<ProductTable
94
products={[
95
{ id: 1, name: 'Cheese', price: 4.9, stock: 20 },
96
{ id: 2, name: 'milk', price: 1.9, stock: 32 },
97
{ id: 3, name: 'Yoghurt', price: 2.4, stock: 12 },
98
{ id: 4, name: 'Heavy Cream', price: 3.9, stock: 9 },
99
{ id: 5, name: 'butter', price: 0.9, stock: 99 },
100
{ id: 6, name: 'Sour Cream ', price: 2.9, stock: 86 },
101
{ id: 7, name: 'Fancy French Cheese 🇫🇷', price: 99, stock: 12 },
102
]}
103
/>
104
</div>
105
);
106
}
107
108
ReactDOM.createRoot(document.querySelector("#root")).render(<App />);
JavaScript
1
45
45
1
body {
2
font-family: 'open sans', sans-serif;
3
font-size: 16px;
4
}
5
6
table {
7
width: 100%;
8
border-collapse: collapse;
9
}
10
11
thead th {
12
text-align: left;
13
border-bottom: 2px solid black;
14
}
15
16
thead button {
17
border: 0;
18
border-radius: none;
19
font-family: inherit;
20
font-weight: 700;
21
font-size: inherit;
22
padding: 0.5em;
23
margin-bottom: 1px;
24
}
25
26
thead button.ascending::after {
27
content: '👇';
28
display: inline-block;
29
margin-left: 1em;
30
}
31
32
thead button.descending::after {
33
content: '☝️';
34
display: inline-block;
35
margin-left: 1em;
36
}
37
38
tbody td {
39
padding: 0.5em;
40
border-bottom: 1px solid #ccc;
41
}
42
43
tbody tr:hover {
44
background-color: #eee;
45
}
JavaScript
1
3
1
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
2
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
3
<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:
JavaScript
1
10
10
1
if (typeof a[sortConfig.key] === "string" && typeof b[sortConfig.key] === "string") {
2
if (a[sortConfig.key].toLowerCase() < b[sortConfig.key].toLowerCase()) {
3
return sortConfig.direction === 'ascending' ? -1 : 1;
4
}
5
} else {
6
if (a[sortConfig.key] < b[sortConfig.key]) {
7
return sortConfig.direction === 'ascending' ? -1 : 1;
8
}
9
}
10