React rendering evaluates components and produces their user-interface output. A functional component renders when mounted, when its parent re-renders, or when a hook flags it for re-render. React may batch multiple causes, so one state change and a parent render can result in one render or two. section 3.1
Use these rules when reasoning about rendering behavior:
- Do not treat changed properties as the only render trigger; parent renders and hook behavior also matter. section 3.0 section 3.1
- Expect child components to render when their parent renders, even when children are self-contained or receive unchanged properties. section 3.2.1
- Use memo() when a component can reuse the same result for identical properties; avoid optimization that adds complexity without measurable benefit. section 3.0 section 3.2.1
- Distinguish a missing dependency array, which runs an effect on every render, from an empty array, which runs it only on initial mounting. section 3.3.2
Controlled to-do input
A to-do component stores the item list and the current input value with useState. Typing updates the input state and repeatedly renders the component and its Items child. Wrapping Items with memo() lets React reuse its result while its items property remains unchanged, reducing work during typing. section 3.2.1
Listing 3.5 A to-do list without memoization
import { useState } from "react";
function Items({ items }) { #1
return (
<>
<h2>Todo items</h2>
<ul>
{items.map((todo) => (
<li key={todo}>{todo}</li>
))}
</ul>
</>
);
}
function Todo() {
const [items, setItems] = useState(["Clean gutter", "Do dishes"]);
const [newItem, setNewItem] = useState("");
const onSubmit = (evt) => {
setItems((items) => items.concat([newItem]));
setNewItem("");
evt.preventDefault();
};
const onChange = #2
(evt) => setNewItem(evt.target.value); #2
return (
<main>
<Items items={items} /> #3
<form onSubmit={onSubmit}>
<input value={newItem} onChange={onChange} />
<button>Add</button>
</form>
</main>
);
}
function App() {
return <Todo />;
}
export default App;
Inspect the runnable to-do implementation without memoization, including controlled input state, item rendering, and the parent-child relationship. section 3.2.1
