React Dynamic Lists map() filter()
Real-world applications often need dynamic lists — lists that can change when users add, remove, or filter items. In React, we manage these lists using component state (usually arrays) and array helper methods such as map(), filter(), and the spread operator [...array].
Mastering dynamic lists is essential for building interactive UIs like to-do apps, product search, or dashboards that respond to user input in real time.
const [todos, setTodos]).map() to convert an array into React elements.filter() to exclude an item and return a new array.filter() with conditions based on user input.push() directly on state).key prop when rendering lists.At the core of dynamic lists are a few powerful patterns:
{'items.map(item => <li key={item.id}>{item.name}</li> )'}setItems([...items, newItem])setItems(items.filter(item => item.id !== idToRemove))const filtered = items.filter(item => item.matchesQuery)These methods do not modify the original array; instead, they return a new array, which is exactly what React expects when updating state.
Store the list in state, expose an input box, and update the array whenever the user clicks an Add button.
// React todo list that lets the user add new tasks dynamically
import React, { useState } from "react";
function TodoList() {
const [todos, setTodos] = useState(["Learn React", "Build App"]);
const [input, setInput] = useState("");
const addTodo = () => {
if (input.trim() === "") return; // Ignore empty or whitespace-only tasks
setTodos([...todos, input]); // Create a new array with the new todo appended
setInput("");
};
return (
<div>
<h4>My Todo List</h4>
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Add new task"
/>
<button className="btn btn-primary ms-2" onClick={addTodo}>
Add
</button>
<ul className="mt-3">
{todos.map((t, index) => (
<li key={index}>{t}</li>
))}
</ul>
</div>
);
}
export default TodoList;
"Learn React" and "Build App".input.trim() to keep the list clean.Use filter() to create a new array that excludes the item to be removed.
// List where each item has a Remove button that filters it out
function RemovableList() {
const [items, setItems] = React.useState(["Pen", "Pencil", "Eraser"]);
const removeItem = (name) => {
setItems(items.filter((item) => item !== name)); // Keep everything except the clicked item
};
return (
<ul>
{items.map((item) => (
<li key={item}>
{item}
<button
className="btn btn-sm btn-danger ms-2"
onClick={() => removeItem(item)}
>
Remove
</button>
</li>
))}
</ul>
);
}
export default RemovableList;
Pen, Pencil, and Eraser.Implement a simple search bar that filters visible items as the user types, without changing the original data.
// Product search list that filters items based on a search query
function FilterableList() {
const [search, setSearch] = React.useState("");
const products = ["Laptop", "Keyboard", "Mouse", "Headphones", "Monitor"];
const filtered = products.filter((p) =>
p.toLowerCase().includes(search.toLowerCase()) // Case-insensitive match with the query
);
return (
<div>
<h4>Product Search</h4>
<input
type="text"
placeholder="Search product..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
<ul className="mt-3">
{filtered.length > 0 ? (
filtered.map((p) => <li key={p}>{p}</li>)
) : (
<li className="text-muted">No products found</li>
)}
</ul>
</div>
);
}
export default FilterableList;
filtered array based on the current search text.A realistic list often needs all three behaviours together: adding items, removing items, and filtering them based on a search query.
// Grocery list that supports adding, removing, and live filtering of items
function SmartList() {
const [list, setList] = React.useState(["Milk", "Bread", "Butter"]);
const [query, setQuery] = React.useState("");
const [input, setInput] = React.useState("");
const addItem = () => {
if (input.trim() === "") return; // Prevent adding empty grocery items
setList([...list, input]);
setInput("");
};
const removeItem = (name) => {
setList(list.filter((item) => item !== name)); // Remove the clicked item from the list
};
const filtered = list.filter((item) =>
item.toLowerCase().includes(query.toLowerCase())
);
return (
<div>
<h4>Grocery List</h4>
<input
type="text"
placeholder="Search..."
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<input
type="text"
placeholder="Add item"
className="ms-2"
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<button className="btn btn-primary ms-2" onClick={addItem}>
Add
</button>
<ul className="mt-3">
{filtered.map((item) => (
<li key={item}>
{item}
<button
className="btn btn-sm btn-outline-danger ms-2"
onClick={() => removeItem(item)}
>
Remove
</button>
</li>
))}
</ul>
</div>
);
}
export default SmartList;
Milk, Bread, and Butter.key when rendering list items (prefer IDs over indexes).setList(prev => [...prev, input]) when the new value depends on the previous state.useMemo() to memoise expensive filtering or sorting on large datasets.push() on state arrays).map() to render lists; use filter() for removal and search.toLowerCase() for case-insensitive matching.useState() and map().filter().sort() before rendering.Goal: Learn how to manage dynamic lists in React using map() and filter(), handle additions and deletions, and render filtered data efficiently.