
ReactJS
Props and state are both ways to pass data to components, but they're for different purposes. Use state for component-owned data, props for external data.
Props come from parent and don't change. State is owned by the component and changes over time. Props are read-only; state can be updated.
State belongs to the component. Props come from outside. Think of props as arguments to a function and state as local variables.
import { useState } from 'react';
function Button(props) {
// Props: come from parent, read-only
// props.label = 'Cannot change this'
// State: owned by component, changeable
const [clicked, setClicked] = useState(0);
return (
<button onClick={() => setClicked(clicked + 1)}>
{props.label} - Clicked {clicked} times
</button>
);
}
// Usage
<Button label="Click me" /><details>
<summary>📚 More Examples</summary>
// Example: Clear separation of props and state
function UserCard(props) {
// Props: data about the user (read-only)
const { userId, userName, email } = props;
// State: UI state for this component (changeable)
const [expanded, setExpanded] = useState(false);
const [liked, setLiked] = useState(false);
return (
<div>
<h3>{userName}</h3>
{expanded && <p>{email}</p>}
<button onClick={() => setExpanded(!expanded)}>
{expanded ? 'Hide' : 'Show'} Details
</button>
<button onClick={() => setLiked(!liked)}>
{liked ? '❤️' : '🤍'} Like
</button>
</div>
);
}</details>
Use this table to decide whether to use state or props:
| Situation | Use |
|---|---|
| Data comes from parent | Props |
| Component manages it | State |
| Multiple components need it | Pass as prop or use Context |
| Doesn't change | Props |
| Changes frequently | State |
| Passed to other components | Props |
| Only this component uses it | State |
import { useState } from 'react';
function TodoApp() {
// State: TodoApp owns the list
const [todos, setTodos] = useState([
{ id: 1, text: 'Learn React' },
]);
// Pass state as props to child
return (
<div>
<TodoList todos={todos} onAddTodo={addTodo} />
</div>
);
}
function TodoList(props) {
// Props: TodoList receives data from parent
// Props: TodoList receives callback to update parent
return (
<ul>
{props.todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}<details>
<summary>📚 More Examples</summary>
// Example: Where should state live?
// ❌ WRONG: Child duplicating parent data
function BadParent() {
const [name, setName] = useState('John');
return <Child name={name} />;
}
function BadChild(props) {
const [name, setName] = useState(props.name); // Duplicate!
// Now it's out of sync with parent
}
// ✅ CORRECT: Parent owns state, child receives via props
function GoodParent() {
const [name, setName] = useState('John');
return (
<div>
<input value={name} onChange={(e) => setName(e.target.value)} />
<Child name={name} />
</div>
);
}
function GoodChild(props) {
// Just read props, don't create state from them
return <p>{props.name}</p>;
}</details>
If multiple components need the same state, move it to their common parent and pass it down as props.
import { useState } from 'react';
function Parent() {
// Move state here so both children can access it
const [count, setCount] = useState(0);
return (
<div>
<Child1 count={count} onIncrement={() => setCount(count + 1)} />
<Child2 count={count} />
</div>
);
}
function Child1(props) {
return (
<div>
<p>Count: {props.count}</p>
<button onClick={props.onIncrement}>+1</button>
</div>
);
}
function Child2(props) {
return <p>Total: {props.count}</p>;
}| Aspect | Props | State |
|---|---|---|
| Owner | Parent | Component |
| Read/Write | Read-only | Read and Write |
| Changes | Don't change | Can change |
| Flow | Top to bottom | Inside component |
| Use for | Configuration | UI, user input |
Ready to practice? Challenges | Next: State and Components
Resources
Ojasa Mirai
Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.
Learn Deep • Build Real • Verify Skills • Launch Forward