As React developers, we've all encountered scenarios where we need to render lists of data. While .map()
method works well, repeating the same logic every time render a list can become exhausting, and leads to code duplication. Fortunately, there's a cleaner, scalable way to handle this, using reusable component, higher order component, or custom hook.
In this article, I'll share an approach for improving list rendering in React, ensuring your code stays DRY, reusable, and easier to maintain.
Main Problem: Repetitive .map()
Logic
Imagine you're building a dashboard for an e-commerce application. The dashboard includes several lists: recent orders, top-selling products, user comments, etc. You need to render each list using a .map()
function. Here's a typical example:
const orders = [...]; // Array of order data
return (
<>
{orders.map((order, index) => (
<OrderComponent key={index} data={order} />
))}
</>
);
Now, you can see repeating the .map()
logic for every list, cluttering your component with similar code. Here’s where reusable pattern can be handy.
Solution: A Reusable ListComponent
To avoid duplicating the .map() logic, we can create a reusable ListComponent that abstracts the mapping logic and allows us to render different components based on the data.
function ListComponent({ data, renderItem }) {
return (
<>
{data.map((item, index) => renderItem(item, index))}
</>
);
}
Usage:
<ListComponent
data={orders}
renderItem={(order, index) => (
<OrderComponent key={index} data={order} />
)}
/>
In this pattern:
renderItem: A function that defines how each item should be rendered
By passing a different renderItem function, we can reuse ListComponent for any list. This results in a clean, reusable component, reducing repetitive .map()
logic.
More Flexibility: Higher-Order Component(HOC)
If multiple components need list rendering, let's take this pattern further by creating a HigherOrder Component. A HOC allows to enhance any component with additional functionality — in this case, list rendering.
function withListRendering(WrappedComponent) {
return function ListWrapper({ data, ...props }) {
return (
<>
{data.map((item, index) => (
<WrappedComponent key={index} data={item} {...props} />
))}
</>
);
};
}
Usage:
const EnhancedOrderComponent = withListRendering(OrderComponent);
// Now render the component with any data array
<EnhancedOrderComponent data={orders} />
By wrapping OrderComponent with the withListRendering HOC, we’ve automatically added list rendering behavior without modifying the original component. This pattern keeps code modular.
For Hook Lovers: Custom Hook for List Rendering
React hooks offer a functional way to encapsulate logic. If you prefer using hooks, here is an example of list rendering with a custom hook.
function useListRenderer(data, renderItem) {
return data.map((item, index) => renderItem(item, index));
}
Usage:
function OrdersDashboard({ orders }) {
const orderList = useListRenderer(orders, (order, index) => (
<OrderComponent key={index} data={order} />
));
return <>{orderList}</>;
}
This approach moves .map()
logic into the hook, keep the rendering logic separate from the component’s structure. It’s another way to keep component lean and focused on presentation.
Real-World Scenario: An E-Commerce Dashboard
Let’s apply this pattern to a real-world scenario. Imagine you’re building an e-commerce admin dashboard where multiple lists of orders, products, reviews, etc need to be rendered.
Using the ListComponent approach, you could render a list of orders like this:
<ListComponent
data={orders}
renderItem={(order, index) => (
<OrderComponent key={index} data={order} />
)}
/>
When we need to render a different list, such as a products, same ListComponent can be reused with different renderItem function:
<ListComponent
data={products}
renderItem={(product, index) => (
<ProductComponent key={index} data={product} />
)}
/>
No need to rewrite the .map()
logic — just reuse the ListComponent with different data and components. This makes codebase more maintainable as it grows.
Conclusion: Clean, Reusable, and Scalable Code
The reusable ListComponent pattern simplifies React list rendering by abstracting the repetitive .map()
logic. Whether you prefer using the basic component approach, HOC, or custom hook, this pattern ensures code is clean and reusable.
Building a React component with multiple lists, consider using one of these patterns to keep components focused on presentation while separating the list logic outside.
What other reusable patterns have you found useful in React? Let me know in the comments! and finally thanks for reading
Top comments (1)
in my opinion, it's not make our code more "scalable", "readable" than use default
.map()
method*Ex: instead of render 1 component, now with this HOC it's need render 2 component when data change. Performance issues.
*more ex: We need to filter or do some calculate stuff logic before render that list.
if we do stuff logic before the return, we need to
useMemo
for each re-render to make sure that function/stuff not re-initialize.like condition rendering use HOC component, we dont need to make more a component just to do simple task like this.