Lists and Keys
Lists and Keys
Section titled “Lists and Keys”Introduction
Section titled “Introduction”React renders lists using JavaScript’s map() method to transform an array into an array of JSX elements. Each element in a rendered list needs a special key prop that gives it a stable, unique identity across renders. Keys help React identify which items changed, were added, or were removed.
Basic List Rendering
Section titled “Basic List Rendering”function FruitList() { const fruits = ['Apple', 'Banana', 'Orange'];
return ( <ul> {fruits.map(fruit => ( <li key={fruit}>{fruit}</li> ))} </ul> );}Explanation: map() transforms each string into a <li> element. The key prop is the fruit name itself — stable and unique.
Why Use map() Instead of forEach()?
Section titled “Why Use map() Instead of forEach()?”forEach() returns undefined. map() returns a new array. Since JSX needs an array of elements, map() is the correct choice.
// ❌ BAD — forEach returns undefined, nothing rendersconst items = [];arr.forEach(item => items.push(<li>{item}</li>));
// ✅ GOOD — map returns an array of elementsconst items = arr.map(item => <li key={item}>{item}</li>);The Key Prop
Section titled “The Key Prop”Keys tell React which array item corresponds to which component instance across renders. This matters when the list changes — items are inserted, deleted, or reordered.
- Stable: The key should stay the same for the same item across renders.
- Unique: No two sibling items should have the same key.
// ✅ GOOD — database ID is stable and unique{users.map(user => ( <UserCard key={user.id} user={user} />))}
// ❌ BAD — Math.random() changes every render, destroys all DOM nodes{users.map(user => ( <UserCard key={Math.random()} user={user} />))}Index as Key: When It’s Safe and When It Breaks
Section titled “Index as Key: When It’s Safe and When It Breaks”Using the array index as a key is a common pitfall:
// ⚠️ Works but fragile{items.map((item, index) => ( <div key={index}>{item}</div>))}When it’s safe:
- The list is static — items are never reordered, inserted, or deleted.
- The list is small and has no stateful children (no inputs, checkboxes).
When it breaks:
- Items are reordered (sort, filter).
- Items are inserted or deleted from the middle.
- Children have local state (input fields lose values).
Example: Index Key Bug
Section titled “Example: Index Key Bug”import { useState } from 'react';
export default function IndexKeyDemo() { const [items, setItems] = useState(['Alice', 'Bob', 'Charlie']);
const deleteFirst = () => setItems(prev => prev.slice(1));
return ( <div> <button onClick={deleteFirst}>Delete First</button> {items.map((item, index) => ( <div key={index}> {/* ❌ Index key — after deletion, "Bob" gets index 0, keeps Alice's input */} {item}: <input placeholder="Comment..." /> </div> ))} </div> );}Why it breaks: When “Alice” is deleted, “Bob” shifts to index 0. React associates the input state with index 0 (which was Alice’s), so Bob’s input shows Alice’s old text. Using key={item} fixes this.
Rendering from JSON Files
Section titled “Rendering from JSON Files”import products from './products.json';
function ProductList() { return ( <div> {products.map(product => ( <div key={product.id} style={{ border: '1px solid #ccc', margin: '8px', padding: '12px' }}> <h3>{product.name}</h3> <p>{product.description}</p> <p>${product.price.toFixed(2)}</p> </div> ))} </div> );}Best Practices
Section titled “Best Practices”💡 Did You Know? Keys only need to be unique among siblings, not globally unique across the entire app. Two different lists can use the same keys.
🚀 Best Practices
- Use database IDs (
user.id,product.id) as keys. - Use stable identifiers like slugs or UUIDs.
- For static lists, index keys are acceptable but prefer stable IDs.
- Never use
Math.random()orDate.now()as keys. - Keys are not passed as props to the component — React uses them internally.
Common Mistakes
Section titled “Common Mistakes”⚠ Missing Key Warning: If you forget the key prop, React logs a warning: Each child in a list should have a unique "key" prop. Always add a key.
⚠ Duplicate Keys: Two siblings with the same key cause unpredictable rendering bugs. React may reuse or skip items.
⚠ Keys on Fragments: If you use <></>, you can’t add a key. Use <Fragment key={id}> instead.
import { Fragment } from 'react';
{items.map(item => ( <Fragment key={item.id}> <dt>{item.name}</dt> <dd>{item.description}</dd> </Fragment>))}Summary
Section titled “Summary”- Use
map()to render lists from arrays. - Use stable, unique
keyprops for list items. - Avoid index keys when lists can change.
- Keys help React identify items across re-renders.