Lesson 80 of 80
Props vs. state isn't a technical distinction — it's a question of who owns a piece of data, and whether it even needs to be stored at all.
12 min read
Every option explains itself — why the right one is right, and why each wrong one is wrong. Miss one and it comes back later on a spaced-repetition schedule.
This topic is about judgment and practical tradeoffs more than a single right answer — a mock interview is the better way to test yourself on it.
Be interviewed on this →Hints without spoilers, and a plain explanation of why a wrong answer was wrong — answered only from this lesson. Free account, no card.
Sign up freeWhat interviewers actually ask about this, and what a strong answer has to cover.
A strong answer covers
Likely follow-ups
"Should this be a prop or state?" is really three separate questions, and answering them in order avoids most of the back-and-forth: Does a parent already own this value, or would more than one component need it? Then it's a prop — lift it up, pass it down. Can this value be computed entirely from props or state you already have? Then it's neither — derive it inline, and don't give it a slot of its own. Only if the value changes within this component, in direct response to something happening here — a keystroke, a timer, a response coming back — does it earn a useState call.
function ProductList({ products }) { // prop: owned by the parent, read-only here
const [searchTerm, setSearchTerm] = useState(""); // state: changes here, from this component's own input
const filteredProducts = products.filter((p) => // derived: recomputed every render, never stored
p.name.toLowerCase().includes(searchTerm.toLowerCase())
);
return (
<>
<input value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} />
<ul>{filteredProducts.map((p) => <li key={p.id}>{p.name}</li>)}</ul>
</>
);
}
All three categories are visible in five lines. products is a prop because ProductList never creates or changes the list itself, only reads what it was handed — some parent component owns the real list. searchTerm is state because it changes in direct response to this component's own user interaction, and nothing outside ProductList needs to know about it moment-to-moment. filteredProducts is neither: it's a pure function of products and searchTerm, both of which already exist. Giving it its own useState would create a second, independent copy of information that's supposed to always match the other two — and the moment someone changes searchTerm through a code path that forgets to also update a filteredProducts state variable, the list on screen and the search box disagree.
searchTerm is state inside ProductList; the moment a parent needs to read it too, lifting it up turns it into a prop passed down, with the state now living one level higher.This lesson is a practical index into two ideas this track already teaches separately: this track's derived-state lesson covers the "don't store what you can compute" half in depth, and this track's composition lesson covers the "lift it instead of duplicating it" half. Treat this one as the decision tree that ties both principles into a single question to ask before reaching for useState.