Rendering lists with .map()
To render a collection of items, transform the array of data into an array of JSX elements using .map():
const students = [
{ id: 1, name: 'Rahim Uddin', cgpa: 3.85 },
{ id: 2, name: 'Karim Ali', cgpa: 3.20 },
{ id: 3, name: 'Fatema Begum', cgpa: 3.95 },
];
function StudentList() {
return (
<ul>
{students.map(student => (
<li key={student.id}>{student.name} — {student.cgpa}</li>
))}
</ul>
);
}
Why key matters
key is a special prop that helps React identify which items changed, were added, or were removed between renders, so it can update the DOM efficiently and preserve component state correctly.
- Use a stable, unique id from your data (
student.id), never the array index if the list can be reordered, filtered, or have items inserted/removed. - Using the array index as a key can cause subtle bugs: input values, focus, or internal state can end up attached to the wrong item after a reorder.
// risky when the list can change order
{students.map((s, index) => <li key={index}>{s.name}</li>)}
// correct
{students.map((s) => <li key={s.id}>{s.name}</li>)}
Filtering before rendering
function HonorRoll({ students }) {
const topStudents = students.filter(s => s.cgpa >= 3.5);
return (
<ul>
{topStudents.map(s => <li key={s.id}>{s.name}</li>)}
</ul>
);
}
Conditional rendering patterns
function StatusBadge({ status }) {
// if / else via early return
if (status === 'loading') return <Spinner />;
if (status === 'error') return <ErrorMessage />;
// ternary for two-way branching inline
return status === 'success' ? <p>Done!</p> : <p>Idle</p>;
}
function Notifications({ count }) {
// && short-circuit for "render or nothing"
return (
<div>
{count > 0 && <span className="badge">{count}</span>}
</div>
);
}
function RoleView({ role }) {
// object lookup instead of a long if/else chain
const views = {
admin: <AdminPanel />,
teacher: <TeacherPanel />,
student: <StudentPanel />,
};
return views[role] ?? <p>Unknown role</p>;
}
Pitfall:
{count && <Badge />}renders a stray0on screen whencountis0, because0is falsy but still gets rendered as text. Use{count > 0 && <Badge />}instead.