What is the difference between state and props in React?
TL;DR
State is data a component owns and can update over time; props are data a component receives from its parent and must treat as read-only. A state update schedules the owning component to render again unless React can apply a same-value bailout; descendants render by default but may also bail out. New props arrive when the parent renders new element descriptions. Together they implement React's one-way data flow: state lives at the lowest common ancestor that needs it, flows down as props, and changes flow back up via callbacks passed as props.
What is the difference between state and props in React?
State is component-owned memory, while props are read-only inputs supplied by the component's parent.
State
State is data a component owns and can change over time, usually in response to user interaction, network responses, or timers. When state changes, React schedules a re-render of that component so the UI reflects the new value.
- State is local: a parent cannot read a child's state directly.
- In function components, state is declared with the
useStatehook (oruseReducerfor more complex transitions). - Setters queue state for a subsequent render and React batches updates where possible. The current handler still sees the state snapshot from the render that created it.
- The term updater function specifically refers to the
setX(prev => next)form passed to a setter — not the setter itself. Use it whenever the next value depends on the previous one, so batched updates compose correctly.
import { useState } from 'react';function Counter() {const [count, setCount] = useState(0);// This works for one click, but repeated queued calls would reuse the same// render snapshot: const increment = () => setCount(count + 1);// Right: the updater function gets the latest valueconst increment = () => setCount((prev) => prev + 1);return (<div><p>Count: {count}</p><button onClick={increment}>Increment</button><buttononClick={() => {// Both updates apply; final count goes up by 2increment();increment();}}>Increment twice</button></div>);}
When a class state update depends on previous state, pass a function such as this.setState((prev) => ({ count: prev.count + 1 })). Reading this.state.count in several queued object-form updates reuses the same snapshot. New code should generally prefer useState in a function component.
Props
Props (short for "properties") are the inputs a parent passes to a child. From the child's perspective they are read-only — you must not assign to them. From the system's perspective they are not "immutable" in any deep sense; the parent simply re-renders with a new value, and the child receives the new props on its next render.
function Parent() {const [name, setName] = useState('World');return (<><input value={name} onChange={(event) => setName(event.target.value)} /><Greeting message={`Hello, ${name}!`} /></>);}function Greeting({ message }) {// Read-only here. Mutating `message` would be a bug.return <p>{message}</p>;}
Props can carry data, JSX (children), and callbacks. Callback props are how children communicate upward — the child invokes the function, the parent updates its state, and new props flow down on the next render.
One-way data flow, lifted state, and derived values
These three ideas tie state and props together:
- One-way data flow. Data moves down the tree as props. To affect a parent, a child calls a function the parent passed in. There is no two-way binding.
- Lifting state up. When two siblings need the same data, move the
useStateto their nearest common ancestor and pass the value (and a setter) down as props. This keeps a single source of truth. - Derived state vs state. Anything you can compute from props or existing state during render should be computed, not stored. Storing a derived value duplicates the source of truth and creates sync bugs; just calculate it in the render body (and reach for
useMemoonly if the computation is expensive).
function Cart({ items }) {// Derived from props — do NOT put this in useStateconst total = items.reduce((sum, item) => sum + item.price, 0);return <p>Total: {total}</p>;}
Key differences
The following table compares ownership, updates, and rendering behavior:
| State | Props | |
|---|---|---|
| Owned by | The component itself | The parent |
| Mutable by | The component, through its setter | The child must treat props as read-only; the parent may pass a new value |
| Triggers re-render of | The owning component | The receiving component, when the parent passes new values |
| Typical use | Internal, changing data | Configuration, data, and callbacks passed in |
Further reading
- React documentation: State — A component's memory
- React documentation: Passing props to a component
- React documentation: Sharing state between components (lifting state up)
- React documentation: Queueing a series of state updates (batching and updaters)
- React documentation: Choosing the state structure (avoiding redundant/derived state)