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 is not allowed to mutate. State changes trigger a re-render of the owning component (and its descendants); prop changes happen because the parent re-rendered with new values. 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
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 are asynchronous and batched — React groups updates triggered in the same event (and, since React 18, also in promises, timeouts, and native event handlers) and re-renders once.
- 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);// Wrong: reads a possibly stale `count` if multiple updates batch together// 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>);}
Class components use
this.setState, but writingthis.setState({ count: this.state.count + 1 })is the exact stale-read anti-pattern the React docs warn against — pass a function (this.setState(prev => ({ count: prev.count + 1 }))) for the same reason. New code should useuseStatein 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
| State | Props | |
|---|---|---|
| Owned by | The component itself | The parent |
| Mutable by | The component (via its setter) | No one (read-only in the child) |
| 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)