Power Up React: Mastering Lists, Keys, and Component Patterns! (React Day 4)
Source: Dev.to
Lists in React
How It Works
Use array methods like map() to transform data into JSX. Each item becomes a component or element.
Practical Example: Basic Todo List
import { useState } from 'react';
function TodoList() {
const [todos, setTodos] = useState(['Buy milk', 'Walk dog', 'Code React']);
return (
{todos.map((todo, index) => (
- {todo}
{/* Keys coming up next! */}
))}
);
}
This renders an unordered list. You can add state updates (e.g., via a form) for dynamism.
UI Scenario
In a shopping cart app:
{cart.map(item => (
))}
Users add/remove items, and the UI updates seamlessly.
Common Error
Forgetting to handle empty lists can cause blank UI. Add a conditional:
{todos.length ? (
todos.map((todo, i) => - {todo}
)
) : (
No todos!
)}
Best Practice
Keep mapping logic simple; extract complex items to sub‑components for readability.
Keys
Keys are unique strings (or numbers) assigned to list items via the key prop. They are not passed to components; they are used internally by React.
Why Keys Matter Internally
During reconciliation (React’s diffing algorithm), keys help identify which items were added, removed, or changed. Without stable keys, React falls back to index‑based matching, which can lead to incorrect updates.
Performance Implications
Proper keys minimize DOM manipulations—React can reuse elements instead of recreating them. Bad keys cause unnecessary re‑renders, flickering UIs, and lost component state (e.g., input focus).
Practical Example: Dynamic List with Stable Keys
function UserList({ users }) {
return (
{users.map(user => (
- {user.name}
{/* Use stable ID like a database key */}
))}
);
}
If users are reordered, keys ensure smooth transitions.
Common Errors
- Using Index as Key – Acceptable only for static lists; disastrous for sortable/filterable lists.
- Duplicate Keys – React warns; keys must be unique among siblings.
- No Keys – Console warning and inefficient rendering.
UI Scenario
In a chat app:
{messages.map(msg => (
))}
Without proper keys, scrolling or new messages could reset focus or break animations.
Best Practice
Use stable, unique IDs (e.g., from an API). Avoid random keys that change on every render.
Component Patterns
Reusable components benefit from clear patterns that promote modularity and separation of concerns.
Common Patterns
- Presentational vs. Container (Smart vs. Dumb) – Presentational components handle UI; containers manage logic (state, data fetching) and pass data down.
- Compound Components – Group related components that share implicit state (e.g.,
…). - Render Props / HOCs – Advanced reuse techniques; hooks often provide a simpler alternative.
Practical Example: Container‑Presentational Split
// Presentational: Pure UI
function UserDisplay({ user }) {
return Name: {user.name}, Age: {user.age};
}
// Container: Logic
import { useState, useEffect } from 'react';
function UserContainer() {
const [user, setUser] = useState(null);
useEffect(() => {
// Simulate fetch
setUser({ name: 'Alex', age: 28 });
}, []);
return user ? :
Loading...
;
}
UI Scenario
A dashboard might have a ChartContainer that fetches data and passes it to a ChartDisplay component, allowing the same display logic to be reused across pages with different queries.
Best Practice
Start simple; refactor into patterns as components grow. TypeScript can help enforce prop contracts for reusable pieces.
Separation of Concerns
Dividing responsibilities—UI vs. logic, state vs. rendering—makes testing, debugging, and collaboration easier.
How to Apply
- Extract logic to custom hooks or utility modules.
- Keep components focused: one component fetches data, another renders it.
Practical Example
The UserContainer above separates data fetching from presentation. The same principle applies to list rendering: a hook fetches users, while UserList only maps them to JSX.
Common Error
Monolithic components that handle fetching, state, and UI become hard to reuse or test. Split them early.
UI Scenario
In a news feed:
FeedContainerhandles API calls, pagination, and error handling.FeedItemsimply renders an article.
You can swap out the display component without touching the data‑fetching logic.
Best Practice
Adopt a “one concern per file” approach:
src/
├─ components/
│ ├─ containers/
│ └─ presentational/
└─ hooks/
This structure reinforces clear boundaries and promotes reusability.