📨 React Props and State — The Core of Every Component
Understand React props vs state with simple examples. Learn one-way data flow, lifting state up, and why mutating state directly breaks React.
Every React component has two kinds of data:
- Props — passed in from a parent (read-only)
- State — owned and updated by the component itself
🧠 Real-world analogy
Think of props as ingredients a chef receives, and state as the dish they're cooking. The chef can't change the ingredients delivered to them, but they fully control how the dish evolves.
🟢 Props
function Welcome({ name, role = 'guest' }) {
return <h1>Hi {name}, you're a {role}</h1>;
}
<Welcome name="Sam" role="admin" />🟣 State (with useState)
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Clicked {count} times
</button>
);
}⬆️ Lifting state up
When two siblings need the same state, move it to their nearest common parent and pass it down as props. This is React's one-way data flow in action.
💡 Never mutate state directly
state.list.push(x) won't re-render. Always create a new value: setList([...list, x]).
💻 Code Examples
Lifting state up
function Parent() {
const [name, setName] = useState('');
return (
<>
<Input value={name} onChange={setName} />
<Preview value={name} />
</>
);
}
function Input({ value, onChange }) {
return <input value={value} onChange={e => onChange(e.target.value)} />;
}
function Preview({ value }) {
return <p>Preview: {value}</p>;
}Output:
Two children share state via the parent — typing in Input updates Preview.
Updating an array (immutably)
const [todos, setTodos] = useState([]);
// ❌ wrong — mutates, no re-render
todos.push('Buy milk');
// ✅ right — new array
setTodos([...todos, 'Buy milk']);Output:
Only the new-array version triggers a re-render.
⚠️ Common Mistakes
- Mutating state directly (`state.x = 1`) instead of calling the setter.
- Reading state right after setting it and expecting the new value — state updates are async and batched.
- Trying to write to props from inside the child — props are read-only.
- Storing derived values in state when you could just compute them in render.
🎯 Interview Questions
Real questions asked at top product and service-based companies.
Q1.What's the difference between props and state?Beginner
Props are inputs from a parent — read-only inside the component. State is internal data managed by the component itself, changed via the setter. Props flow down; state stays local.
Q2.Can a component modify its own props?Beginner
No. Props are immutable from the receiver's perspective. To change them, the parent must re-render with new values.
Q3.What is 'lifting state up'?Intermediate
Moving shared state to the nearest common ancestor of components that need it, then passing it down as props. This keeps state in one place and respects React's one-way data flow.
Q4.Is setState synchronous or asynchronous?Intermediate
Asynchronous and batched. After calling setState, the variable still holds the old value until the next render. Use the functional updater `setCount(c => c + 1)` if the new value depends on the previous one.
Q5.Why does mutating state directly break React?Advanced
React compares previous and next state references to decide whether to re-render. Mutating the same object means the reference is unchanged, so React skips the update. Creating a new object/array forces a fresh reference.
🧠 Quick Summary
- Props come from parent and are read-only.
- State is local and changed via its setter.
- Lift shared state up to the common parent.
- Never mutate state — always create new references.
- useState returns [value, setValue].