HVRDHVRD
ReactJS

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:

  1. Props — Short for properties, these are inputs passed from parent to child components.
    Think of them as arguments you send into a function.

  2. 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 called count, initialized to 0.
  • setCount is 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

ConceptOwnershipCan Modify Itself?Accessible ByCommon Use
PropsParent❌ NoChildPassing data down
StateComponent itself✅ YesItself onlyDynamic 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:

  • TodoList manages state (todos).
  • TodoItem receives 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.