What is lazy initialisation in useState, and when should you use it?
Pass a function to useState, as in useState(() => compute()). React runs it only on the first render. Without the function form, the expensive call runs on every render, even though its result is ignored after the first.
Explain it simply
Imagine you pack a full suitcase every morning but only use the first one. Wasteful. useState(compute()) calls compute() on every render because JavaScript evaluates the argument before React sees it; React just ignores the result after the first time.
Passing () => compute() hands React a recipe instead. React cooks it once, on mount.
Example
function Notes() {
// runs JSON.parse on every render
const [a] = useState(JSON.parse(localStorage.getItem("notes") || "[]"));
// runs only once
const [b] = useState(() => JSON.parse(localStorage.getItem("notes") || "[]"));
return <p>{b.length} notes</p>;
}For cheap values like 0 or "", the plain form is fine.
What to say in the interview
"The argument to useState is evaluated every render unless it is a function. With a lazy initialiser, React calls it only on the first render. I use it for work like parsing localStorage or building a large structure, and pass a plain value for cheap defaults."
Common mistakes
- Passing the result of the function call, useState(init()), instead of the function itself, useState(init).