What is the difference between state and props
Props are inputs passed into a component by its parent — read-only from the component's view. State is data the component owns and manages internally, and can change over time. Props flow down and are immutable; state is local, mutable (via setState), and triggers re-renders.
Both props and state are plain JS objects that hold data and, when changed, cause a re-render. The difference is ownership and mutability.
Props — passed in, read-only
- Passed from a parent to a child component — the component's inputs/arguments.
- Read-only / immutable from the receiving component's perspective — a component must never modify its own props.
- Owned by the parent — only the parent can change them (by re-rendering with new values).
- Make components configurable and reusable — same component, different props, different output.
function Greeting({ name }) { // 'name' is a prop
return <h1>Hello, {name}</h1>; // read-only — never reassign it
}
<Greeting name="Atul" />State — owned and managed internally
- Owned by the component itself, declared with
useState/useReducer. - Mutable — but only via the setter (
setState); never mutate it directly. - Private — local to the component (unless deliberately passed down as props).
- Represents data that changes over time due to interaction, async results, etc.
function Counter() {
const [count, setCount] = useState(0); // 'count' is state
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}The comparison
| Props | State | |
|---|---|---|
| Source | passed from parent | declared in the component |
| Owner | the parent | the component itself |
| Mutability | read-only | mutable via setter |
| Scope | flows down to children | local/private |
| Purpose | configure/reuse | track changing data |
| Triggers re-render | yes (when parent passes new) | yes (when setter called) |
The connection: data flows down
A parent's state is often passed to children as props. So one component's state becomes another's props. This is React's one-way data flow — data goes down via props, changes go up via callbacks (which a parent uses to update its state).
function Parent() {
const [user, setUser] = useState(null); // state here...
return <Profile user={user} />; // ...passed down as a prop
}Common confusions to clear up
- "Can a child change props?" — No. It can call a callback prop to ask the parent to change its state.
- Both cause re-renders; the difference isn't whether they re-render, it's who controls them.
- Derived data shouldn't be state — if you can compute it from props/state, compute it, don't store it.
How to answer
"Props are a component's inputs — passed in by the parent, read-only from the component's view. State is data the component owns and manages itself, changeable over time via its setter. Props flow down and are immutable; state is local and mutable. They connect through one-way data flow: a parent's state is frequently passed to children as props, and children request changes via callback props."
Follow-up questions
- •Can a child component modify its props? How does it request a change?
- •How do state and props connect through one-way data flow?
- •When should something be state vs derived/computed?
- •What's 'lifting state up' and why do it?
Common mistakes
- •Mutating props inside a component.
- •Mutating state directly instead of using the setter.
- •Storing derived data in state instead of computing it.
- •Thinking the difference is about re-rendering — it's about ownership.
- •Copying props into state unnecessarily (causes sync bugs).
Performance considerations
- •Both trigger re-renders. New prop references each render can break memoized children. State should be colocated to limit re-render scope; derived values computed, not stored.
Edge cases
- •Initializing state from a prop (and the staleness pitfall).
- •Derived state that should just be computed.
- •Lifting state up when two siblings need to share it.
- •Callback props as the channel for child-to-parent communication.
Real-world examples
- •A parent holding form state, passing values down as props and receiving changes via onChange callbacks.