0 day streak
javascript / intermediate
Snippet

Grouping Tabular Data by Category Using Array Reduce Inside Custom Hooks

Array.prototype.reduce allows transforming a flat list of objects into an indexed lookup dictionary grouped by dynamic keys. Encapsulating this pure data transformation inside a custom hook with useMemo prevents unnecessary recalculations during re-renders.

snippet.js
javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { useMemo } from 'react';
function useGroupedInventory(items) {
return useMemo(() => {
return items.reduce((accumulator, currentItem) => {
const category = currentItem.category ?? 'Unassigned';
if (!accumulator[category]) {
accumulator[category] = [];
}
accumulator[category].push(currentItem);
return accumulator;
}, {});
}, [items]);
}
export function InventoryList({ items }) {
const grouped = useGroupedInventory(items);
return (
<div>
{Object.entries(grouped).map(([category, list]) => (
<section key={category}>
<h3>{category} ({list.length})</h3>
<ul>
{list.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
</section>
))}
</div>
);
}
react
Breakdown
1
return items.reduce((accumulator, currentItem) => {
Iterates through the source array, accumulating aggregated category buckets into an object.
2
const category = currentItem.category ?? 'Unassigned';
Uses nullish coalescing to provide a safe fallback bucket when a category key is undefined or null.
3
accumulator[category].push(currentItem);
Appends the current item reference into the appropriate category array within the accumulator.
4
Object.entries(grouped).map(([category, list]) => (
Transforms the grouped object into key-value pairs for declarative JSX rendering.