DEV Community

Cover image for Enhancing React List Rendering: A Clean and Reusable Pattern
Md Readwan
Md Readwan

Posted on

Enhancing React List Rendering: A Clean and Reusable Pattern

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} />
    ))}
  </>
);
Enter fullscreen mode Exit fullscreen mode

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))}
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Usage:

<ListComponent 
  data={orders} 
  renderItem={(order, index) => (
    <OrderComponent key={index} data={order} />
  )} 
/>
Enter fullscreen mode Exit fullscreen mode

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} />
        ))}
      </>
    );
  };
}
Enter fullscreen mode Exit fullscreen mode

Usage:

const EnhancedOrderComponent = withListRendering(OrderComponent);

// Now render the component with any data array
<EnhancedOrderComponent data={orders} />
Enter fullscreen mode Exit fullscreen mode

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));
}
Enter fullscreen mode Exit fullscreen mode

Usage:

function OrdersDashboard({ orders }) {
  const orderList = useListRenderer(orders, (order, index) => (
    <OrderComponent key={index} data={order} />
  ));

  return <>{orderList}</>;
}
Enter fullscreen mode Exit fullscreen mode

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} />
  )} 
/>
Enter fullscreen mode Exit fullscreen mode

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} />
  )} 
/>
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
hoanggbao profile image
hoanggbao00 • Edited

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.