Click a counter’s Increment button and its displayed value changes. The state setter updates the value, then React runs the component’s rendering logic again to produce the new output. Clicking Reset when the value is already 0 is different: with useState, setting the same value does not cause a re-render. section 5.2.5
A functional component renders when:
- It mounts—appearing in the component tree for the first time. section 6.2
- Its parent renders. A child can run again even when its props have not changed. section 6.2.2
- A stateful hook updates its value. React may batch nearby triggers, so do not rely on a particular number of renders. section 6.2 section 6.2.3
A to-do button that does nothing
Mutating an array with `todos.splice(index, 1)` and then calling `setTodos(todos)` passes the same array back to the setter; the list does not re-render. Instead, create an array without that item: `setTodos(value => [...value.slice(0, index), ...value.slice(index + 1)])`. The new state value lets React render the updated list. section 5.2.5
Listing 5.7 A proper to-do list application
import { useState } from "react";
function TodoApplication({ initialList }) {
const [todos, setTodos] = useState(initialList);
return (
<main>
{todos.map((todo, index) => (
<p key={todo}>
{todo}
<button
onClick={() => {
setTodos((value) => [ #1
...value.slice(0, index), #1
...value.slice(index + 1), #1
]);
}}
>
x
</button>
</p>
))}
</main>
);
}
function App() {
const items = ["Feed the plants", "Water the dishes", "Clean the cat"];
return <TodoApplication initialList={items} />;
}
export default App;
See the working removal handler create a new array before updating state. section 5.2.5
Keep rapidly changing details out of state when the UI only needs a simpler answer. For a background that changes when the pointer crosses the middle, storing every pointer position causes repeated renders; storing only which side the pointer is on renders when that answer changes. React Developer Tools can highlight components as they render when you need to check what is happening. section 6.2.3 section 5.2.5
Do not assume rendering repeats initialization. A class constructor runs once, even though `render` can run again; an ID created inside `render` would be regenerated. Also note the class-state difference: calling `setState` re-renders a class component even with unchanged values, unlike setting an unchanged value through useState. section 4.4.4 section 5.3.2


