← Về danh sách bài họcBài 18/25
📋 Bài 18: Conditional Rendering & Lists
🎯 Sau bài học này, bạn sẽ:
- Dùng if/ternary/&& cho conditional rendering
- Render lists với map() và key prop
- Hiểu tại sao key quan trọng cho performance
- Filter và sort lists hiệu quả
1. Conditional Rendering
function Dashboard({ user, notifications, role }) {
// Early return
if (!user) return <p>Vui lòng đăng nhập</p>;
return (
<div>
{/* Ternary */}
{user.isPremium
? <PremiumBadge />
: <UpgradeButton />
}
{/* && operator */}
{notifications > 0 && (
<span className="badge">{notifications}</span>
)}
{/* Render theo điều kiện phức tạp */}
{(() => {
switch(role) {
case 'admin': return <AdminPanel />;
case 'editor': return <EditorPanel />;
default: return <UserPanel />;
}
})()}
</div>
);
}2. Rendering Lists
function TodoList() {
const [todos, setTodos] = useState([
{ id: 1, text: 'Học React', done: false },
{ id: 2, text: 'Làm project', done: true }
]);
const [filter, setFilter] = useState('all');
// Filter + Sort
const filteredTodos = todos
.filter(todo => {
if (filter === 'active') return !todo.done;
if (filter === 'done') return todo.done;
return true;
})
.sort((a, b) => a.done - b.done);
return (
<div>
<select value={filter} onChange={e => setFilter(e.target.value)}>
<option value="all">Tất cả</option>
<option value="active">Chưa xong</option>
<option value="done">Đã xong</option>
</select>
<ul>
{filteredTodos.map(todo => (
<li key={todo.id} style={{
textDecoration: todo.done ? 'line-through' : 'none'
}}>
{todo.text}
</li>
))}
</ul>
{filteredTodos.length === 0 && <p>Không có todo nào.</p>}
</div>
);
}⚠️ Key prop: Luôn dùng unique, stable ID làm key. KHÔNG dùng index làm key khi list có thể thay đổi thứ tự (thêm/xóa/sort).
📝 Tóm Tắt
- Conditional: ternary (
? :),&&, early return - Lists:
.map()vớikeyprop (dùng unique ID) - Filter:
.filter()trước.map() - Empty state: luôn xử lý trường hợp list rỗng