State and events · Lesson 8 of 21
Objects and arrays in state
Don't mutate, make a new copy: spread, map and filter.
React compares old and new state with Object.is: "is this the same object?" If you change the object itself (user.name = …) and set it again, React sees the same object and skips the re-render. The rule: make a new copy with the change.
function App() {
const [profile, setProfile] = useState({ name: "Karim", city: "Alexandria", xp: 150 })
const [tags, setTags] = useState(["web", "data"])
return (
<div>
<p>{profile.name} · {profile.city} · {profile.xp} xp</p>
<button onClick={() => setProfile({ ...profile, xp: profile.xp + 50 })}>+50 xp</button>
<button onClick={() => setProfile({ ...profile, city: "Cairo" })}>Move to Cairo</button>
<p>{tags.join(", ")}</p>
<button onClick={() => setTags([...tags, "ai"])}>Add tag</button>
<button onClick={() => setTags(tags.filter((t) => t !== "web"))}>Remove web</button>
<button onClick={() => setTags(tags.map((t) => t.toUpperCase()))}>Uppercase</button>
</div>
)
}| To | ❌ mutates | ✅ new copy |
|---|---|---|
add | arr.push(x) | [...arr, x] |
remove | arr.splice(i, 1) | arr.filter((_, j) => j !== i) |
replace | arr[i] = x | arr.map((v, j) => j === i ? x : v) |
sort | arr.sort() | [...arr].sort() |
change a field | obj.x = 1 | { ...obj, x: 1 } |
Spot the bug
The button adds the task (see the console) but the screen doesn't update. Which line?
Exercise
A task list: each task has a done button that removes it, and the first line shows N left. The checker presses the first button twice.
1 left Quiz done
function App() {
const [tasks, setTasks] = useState(["Read", "Practice", "Quiz"])
return (
<div>
<p>{tasks.length} left</p>
<ul>
{tasks.map((t) => (
<li key={t}>{t} <button>done</button></li>
))}
</ul>
</div>
)
}Learn more from
Played 0 of 2 games
Sign in to save your progress and earn XP.