Dynamic Rendering with Lists and Arrays

Introduction

One of React’s most powerful features is the ability to dynamically render content based on data. In modern web applications, content rarely remains static; users interact with apps, APIs return changing data, and components must respond accordingly. React allows developers to render lists, tables, menus, and other repetitive elements dynamically using arrays and mapping functions.

Dynamic rendering improves efficiency, maintainability, and scalability of your application. Instead of manually writing multiple elements in JSX, React can automatically generate components from data arrays.

In this post, we will explore dynamic rendering with lists and arrays in React, including:

  • Basics of rendering arrays
  • Mapping arrays to JSX elements
  • Using keys for efficient updates
  • Conditional rendering with lists
  • Nested lists
  • Complex state updates
  • Best practices
  • Real-world examples

By the end of this post, you will be able to handle dynamic rendering confidently in any React application.


Rendering Static Lists

Before diving into dynamic rendering, let’s review rendering static arrays.

function StaticList() {
  const fruits = ["Apple", "Banana", "Cherry"];

  return (
<ul>
  <li>{fruits[0]}</li>
  <li>{fruits[1]}</li>
  <li>{fruits[2]}</li>
</ul>
); }

While this works, it is not scalable. Adding or removing items requires manually editing JSX.


Dynamic Rendering with map()

The standard approach to dynamically render lists in React is using the JavaScript map() function. This transforms an array into an array of JSX elements.

function FruitList() {
  const fruits = ["Apple", "Banana", "Cherry"];

  return (
<ul>
  {fruits.map((fruit, index) => (
    <li key={index}>{fruit}</li>
  ))}
</ul>
); }

Here:

  • map() iterates over each array element.
  • key provides a unique identifier for React to track DOM elements.
  • JSX elements are generated dynamically based on array content.

Importance of Keys

Keys are essential in dynamic rendering. React uses keys to identify elements between renders. Without keys, React may unnecessarily re-render elements or mix up their state.

Bad Example (No Keys)

<ul>
  {fruits.map(fruit => <li>{fruit}</li>)}
</ul>

This generates a warning in the console:
“Each child in a list should have a unique key prop.”

Good Example (Using Unique IDs)

const fruits = [
  { id: 1, name: "Apple" },
  { id: 2, name: "Banana" },
  { id: 3, name: "Cherry" }
];

<ul>
  {fruits.map(fruit => <li key={fruit.id}>{fruit.name}</li>)}
</ul>

Best practice: Always use unique IDs for keys, not array indexes, especially for dynamic lists that may change.


Rendering Lists of Components

Dynamic rendering is more powerful when rendering custom components instead of plain HTML elements.

function Fruit({ name }) {
  return <li>{name}</li>;
}

function FruitList() {
  const fruits = ["Apple", "Banana", "Cherry"];

  return (
&lt;ul&gt;
  {fruits.map((fruit, index) =&gt; (
    &lt;Fruit key={index} name={fruit} /&gt;
  ))}
&lt;/ul&gt;
); }

Benefits:

  • Component encapsulation for reusable logic
  • Easier to add behavior like onClick handlers or styling

Conditional Rendering in Lists

Dynamic lists often require conditional rendering, such as highlighting selected items or filtering visible data.

Example: Highlight Completed Tasks

function TaskList({ tasks }) {
  return (
&lt;ul&gt;
  {tasks.map(task =&gt; (
    &lt;li
      key={task.id}
      style={{ textDecoration: task.completed ? "line-through" : "none" }}
    &gt;
      {task.title}
    &lt;/li&gt;
  ))}
&lt;/ul&gt;
); } const tasks = [ { id: 1, title: "Learn React", completed: true }, { id: 2, title: "Build App", completed: false } ];

This approach dynamically adjusts the style or behavior based on the array’s properties.


Nested Lists

Sometimes lists contain nested arrays, such as categories with items or comments with replies.

const categories = [
  { id: 1, name: "Fruits", items: ["Apple", "Banana"] },
  { id: 2, name: "Vegetables", items: ["Carrot", "Spinach"] }
];

function CategoryList() {
  return (
&lt;div&gt;
  {categories.map(category =&gt; (
    &lt;div key={category.id}&gt;
      &lt;h3&gt;{category.name}&lt;/h3&gt;
      &lt;ul&gt;
        {category.items.map((item, index) =&gt; (
          &lt;li key={index}&gt;{item}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  ))}
&lt;/div&gt;
); }

Key points:

  • Outer and inner lists require keys
  • Nested mapping enables rendering complex hierarchical data

Dynamic Rendering with State

Dynamic rendering is often combined with state for interactive lists.

Example: Adding Items

function TodoApp() {
  const [todos, setTodos] = React.useState(["Learn React"]);

  const addTodo = () => {
setTodos(&#91;...todos, "Build a new app"]);
}; return (
&lt;div&gt;
  &lt;ul&gt;
    {todos.map((todo, index) =&gt; (
      &lt;li key={index}&gt;{todo}&lt;/li&gt;
    ))}
  &lt;/ul&gt;
  &lt;button onClick={addTodo}&gt;Add Todo&lt;/button&gt;
&lt;/div&gt;
); }

The UI updates dynamically whenever the state changes.


Removing Items Dynamically

You can remove items by filtering the array.

function TodoApp() {
  const [todos, setTodos] = React.useState([
{ id: 1, text: "Learn React" },
{ id: 2, text: "Build Project" }
]); const removeTodo = (id) => {
setTodos(todos.filter(todo =&gt; todo.id !== id));
}; return (
&lt;ul&gt;
  {todos.map(todo =&gt; (
    &lt;li key={todo.id}&gt;
      {todo.text} &lt;button onClick={() =&gt; removeTodo(todo.id)}&gt;Remove&lt;/button&gt;
    &lt;/li&gt;
  ))}
&lt;/ul&gt;
); }

Key points:

  • Avoid mutating the original array
  • Use filter() or map() to create updated arrays
  • Re-rendering happens automatically with state updates

Updating Items Dynamically

You can update array elements dynamically without mutating the original array.

function TodoApp() {
  const [todos, setTodos] = React.useState([
{ id: 1, text: "Learn React", completed: false },
{ id: 2, text: "Build Project", completed: false }
]); const toggleComplete = (id) => {
setTodos(
  todos.map(todo =&gt;
    todo.id === id ? { ...todo, completed: !todo.completed } : todo
  )
);
}; return (
&lt;ul&gt;
  {todos.map(todo =&gt; (
    &lt;li
      key={todo.id}
      style={{ textDecoration: todo.completed ? "line-through" : "none" }}
    &gt;
      {todo.text}
      &lt;button onClick={() =&gt; toggleComplete(todo.id)}&gt;Toggle&lt;/button&gt;
    &lt;/li&gt;
  ))}
&lt;/ul&gt;
); }

This demonstrates dynamic updates with state management.


Filtering Lists

Dynamic rendering often involves filtering arrays based on conditions.

function FilteredList({ items, search }) {
  const filtered = items.filter(item =>
item.toLowerCase().includes(search.toLowerCase())
); return (
&lt;ul&gt;
  {filtered.map((item, index) =&gt; (
    &lt;li key={index}&gt;{item}&lt;/li&gt;
  ))}
&lt;/ul&gt;
); }

Dynamic filtering can be combined with input elements to create search or live filter features.


Sorting Lists

You can dynamically sort arrays before rendering:

function SortedList({ items }) {
  const sorted = [...items].sort();
  return (
&lt;ul&gt;
  {sorted.map((item, index) =&gt; (
    &lt;li key={index}&gt;{item}&lt;/li&gt;
  ))}
&lt;/ul&gt;
); }

Sorting can also be dynamic using state to toggle ascending/descending order.


Dynamic Rendering with Objects

Sometimes you need to render object arrays dynamically.

const users = [
  { id: 1, name: "Alice", age: 25 },
  { id: 2, name: "Bob", age: 30 }
];

function UserList() {
  return (
&lt;ul&gt;
  {users.map(user =&gt; (
    &lt;li key={user.id}&gt;{user.name} - {user.age} years&lt;/li&gt;
  ))}
&lt;/ul&gt;
); }

Handling Large Arrays Efficiently

For large datasets:

  1. Use keys efficiently
  2. Use React.memo to avoid unnecessary re-renders
  3. Virtualize lists with libraries like react-window
import { FixedSizeList as List } from 'react-window';

function BigList({ items }) {
  return (
&lt;List height={400} itemCount={items.length} itemSize={35} width={300}&gt;
  {({ index, style }) =&gt; (
    &lt;div style={style}&gt;{items&#91;index]}&lt;/div&gt;
  )}
&lt;/List&gt;
); }

Virtualization renders only visible elements, improving performance.


Nested and Dynamic Component Rendering

You can combine arrays, components, and state to create dynamic nested UI.

function CategoryList({ categories }) {
  return (
&lt;div&gt;
  {categories.map(category =&gt; (
    &lt;div key={category.id}&gt;
      &lt;h2&gt;{category.name}&lt;/h2&gt;
      &lt;ul&gt;
        {category.items.map(item =&gt; (
          &lt;li key={item.id}&gt;{item.name}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  ))}
&lt;/div&gt;
); } const data = [ { id: 1, name: "Fruits", items: [{ id: 1, name: "Apple" }, { id: 2, name: "Banana" }] }, { id: 2, name: "Vegetables", items: [{ id: 3, name: "Carrot" }, { id: 4, name: "Spinach" }] } ];

Best Practices for Dynamic Rendering

  1. Always use unique keys for elements.
  2. Avoid mutating arrays directly; use immutable updates (map, filter, slice).
  3. Use small reusable components

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *