Why key is needed when rendering a list in React
TL;DR: Always give list items a key so React knows which ones are the same and which changed.
Why key Matters: Sorting Example
Imagine you have a list of fruits:
const items = [
{ id: 1, name: "Apple" },
{ id: 2, name: "Banana" },
{ id: 3, name: "Cherry" },
];
<ul>
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>;Case 1: With proper unique keys (id)
- Initial render:
Apple,Banana,Cherry. - User clicks sort → new order:
Cherry,Banana,Apple. - React sees the keys
[3, 2, 1]and understands:- The DOM element for
id=3(Cherry) already exists — just move it to the top. - Same for Banana and Apple.
- The DOM element for
- ✅ Result: Fast, efficient, minimal DOM changes.
Case 2: Using array index as key
- Keys are based on position:
[0, 1, 2]. - After sorting, the items change order, but keys stay
[0, 1, 2]. - React thinks:
- “The item at
key=0is still first — but now it’s Cherry, not Apple.” - It reuses the first DOM node but overwrites its content.
- “The item at
- ❌ Result: All list items get re-rendered, even though we just wanted to move them.
Takeaway
- Stable, unique keys (like an
id) let React reuse DOM elements and just move them when the list changes. - Using array indexes (or no key) can cause unnecessary re-renders or even bugs in stateful components like inputs.
Conditional rendering in React
- Typically you'll see "short-circuiting"
- Short-circuiting or short-circuit evaluation is a behavior of logical operators where the evaluation of the second operand (or subsequent operands) is skipped if the result of the entire expression can be determined by the first operand alone.
{
pokemons.length > 0 && (
<ul>
{pokemons.map((pokemon) => {
return <li key={pokemon.name}>{pokemon.name}</li>;
})}
</ul>
);
}Can you use a regular if statement?
Yes — but you can't put a raw if directly inside JSX (since JSX is just an expression). Instead, you can use an if statement to set a variable, and use that variable later on.
function App() {
const [pokemons, setPokemons] = useState([]);
let content;
if (pokemons.length > 0) {
content = (
<ul>
{pokemons.map((pokemon) => (
<li key={pokemon.name}>{pokemon.name}</li>
))}
</ul>
);
}
return (
<div>
<button
type="button"
onClick={() => {
fetchPokemons().then((response) => {
setPokemons(response.results);
});
}}
>
Show Pokemon
</button>
{content}
</div>
);
}
