Props and State
A detailed explanation on how state and props work in React, their differences, and how they enable dynamic, reusable, and interactive component-driven development.
React components are more than static templates—they’re dynamic, data-driven building blocks.
At the heart of this dynamism are state and props.
Together, they define what a component shows and how it behaves based on changing data.
Understanding how state and props flow through your app is the difference between writing React that just works—and writing React that scales elegantly.
The Two Pillars of React Data Flow
In React, there are two primary ways to handle data inside components:
-
Props — Short for properties, these are inputs passed from parent to child components.
Think of them as arguments you send into a function. -
State — Internal, private data that lives inside a component and changes over time.
Think of it as a component’s personal memory.
Props — Making Components Reusable
Props allow a component to be customized without rewriting it.
They turn a static component into something reusable and adaptable.
Example: A Static Component
function Welcome() {
return <h2>Hello, Harsha!</h2>;
}This works, but it’s rigid—what if you need to greet multiple people?
You’d have to copy-paste or hardcode new components.
Enter Props
function Welcome({ name }) {
return <h2>Hello, {name}!</h2>;
}Now, Welcome becomes reusable. You can pass different names to it like so:
function App() {
return (
<div>
<Welcome name="Harsha" />
<Welcome name="Aditi" />
<Welcome name="Ravi" />
</div>
);
}Each Welcome instance renders differently, based on the name prop it receives.
This is one of React’s superpowers—the same component, infinite variations.
How Props Flow
Props always flow downward from parent to child.
The child component can use them, but cannot modify them.
This one-way data flow ensures predictability.
If something changes, you know exactly where that change originated.
State — The Component’s Internal Memory
Props are great for passing data in, but what about data that changes over time inside a component?
That’s where state steps in.
State is internal data that belongs to a component.
When state changes, React automatically re-renders that component—no manual DOM manipulation needed.
Example: A Counter Component
import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}Let’s break this down:
useState(0)creates a state variable calledcount, initialized to0.setCountis a function that updates that state.- Every time you call
setCount, React re-renders the component with the new value.
That’s it—no direct DOM updates, no document queries, just clean reactivity.
The React Way: Declarative UI
React’s state system makes your UI declarative, not imperative.
You don’t tell React how to update the DOM; you just describe what the UI should look like given the current state.
For example:
<p>You clicked {count} times</p>When count changes, React automatically updates this text.
You never touch the DOM—React handles it.
Combining State and Props
The real magic happens when you combine props and state across multiple components.
Example: Parent Controls Child via Props
Let’s say you have a parent component that manages a counter’s state, and a child component that displays and controls it.
function CounterDisplay({ count, onIncrement }) {
return (
<div>
<p>Count: {count}</p>
<button onClick={onIncrement}>Add One</button>
</div>
);
}
function App() {
const [count, setCount] = useState(0);
const handleIncrement = () => setCount(count + 1);
return (
<div>
<h1>Shared Counter Example</h1>
<CounterDisplay count={count} onIncrement={handleIncrement} />
</div>
);
}Here’s what’s happening:
- The App component holds the state (
count). - It passes that state down as a prop to
CounterDisplay. - It also passes a function (
onIncrement) so the child can trigger changes.
The child doesn’t own the state—it just receives it and tells the parent when to change it.
This keeps the data flow predictable and organized.
The Rule of Thumb
| Concept | Ownership | Can Modify Itself? | Accessible By | Common Use |
|---|---|---|---|---|
| Props | Parent | ❌ No | Child | Passing data down |
| State | Component itself | ✅ Yes | Itself only | Dynamic updates, interactivity |
This distinction is crucial for structuring your React app logically and avoiding unpredictable data behavior.
A More Interactive Example
Let’s combine both concepts into something slightly more complex.
function TodoItem({ text, onRemove }) {
return (
<li>
{text}
<button onClick={onRemove}>Remove</button>
</li>
);
}
function TodoList() {
const [todos, setTodos] = useState(["Learn React", "Build a project"]);
const removeTodo = (index) => {
setTodos(todos.filter((_, i) => i !== index));
};
return (
<div>
<h2>Todo List</h2>
<ul>
{todos.map((item, index) => (
<TodoItem
key={index}
text={item}
onRemove={() => removeTodo(index)}
/>
))}
</ul>
</div>
);
}This example demonstrates how:
TodoListmanages state (todos).TodoItemreceives props (text,onRemove) to render and act on that data.- Removing a todo triggers a state update, and React efficiently re-renders the updated list.
Everything flows downward through props, and actions bubble upward through callbacks.
Simple, scalable, and intuitive.
Why State and Props Matter
React’s component model wouldn’t exist without these two concepts:
- Props make components reusable and configurable.
- State makes components dynamic and interactive.
Together, they form the heartbeat of every React app.
Think of props as data inputs and state as data in motion.
Every time state changes, React synchronizes the UI to reflect it—automatically.
Introduction to React
A walkthrough of how React starts from index.html, attaches to the root element via main.jsx, renders App.jsx, and uses components for reusability and dynamic rendering.
React Hooks
Comprehensive guide to React Hooks, covering core concepts, commonly used hooks, custom hooks, rules of hooks, and advanced usage patterns with detailed explanations and code examples.