Chapter 24 โ€” Props vs State

๐Ÿ“– Definition

  • Props โ€” read-only inputs passed from a parent to a child component.
  • State โ€” internal, mutable data managed within a component.

๐Ÿ” Explanation

Aspect Props State
Owner Parent The component itself
Mutable inside the component? โŒ No (immutable) โœ… Yes (via setter)
Triggers re-render? When parent passes a new value When setter is called
Purpose Configuration / data passing Local UI behavior
Initial value? Always from parent Set on first render

๐Ÿ’ป Code Example โ€” Props

function Welcome({ name, role }) {
  return <h2>Welcome, {role} {name}!</h2>;
}

// Parent
<Welcome name="Soumya" role="Engineer" />

name and role are received in props and are read-only inside Welcome.

๐Ÿ’ป Code Example โ€” State

function Counter() {
  const [count, setCount] = useState(0);     // initial state = 0

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>+</button>
      <button onClick={() => setCount(count - 1)}>โˆ’</button>
    </div>
  );
}

๐Ÿ’ป Code Example โ€” Props + State Together

function Counter({ initial = 0 }) {           // props = initial value
  const [count, setCount] = useState(initial); // state holds current count
  return (
    <button onClick={() => setCount(count + 1)}>{count}</button>
  );
}

<Counter initial={5} />

๐Ÿ’ป Code Example โ€” Lifting State Up

When two siblings need to share state, move it to their common parent.

function TemperatureInput({ value, onChange }) {   // โ† controlled by parent
  return <input value={value} onChange={(e) => onChange(e.target.value)} />;
}

function Converter() {
  const [celsius, setCelsius] = useState("");

  return (
    <>
      <TemperatureInput value={celsius} onChange={setCelsius} />
      <p>Fahrenheit: {celsius ? (celsius * 9 / 5 + 32) : "-"}</p>
    </>
  );
}

๐Ÿ’ป Code Example โ€” State Updates Are Asynchronous

function Counter() {
  const [count, setCount] = useState(0);

  const tripleIncrement = () => {
    setCount(count + 1);          // queues 1
    setCount(count + 1);          // STILL queues 1 โ€” `count` is stale
    setCount(count + 1);          // STILL queues 1
  };

  // โŒ result: count becomes 1, not 3

  const tripleIncrementFixed = () => {
    setCount(c => c + 1);         // โœ… functional updates
    setCount(c => c + 1);
    setCount(c => c + 1);
  };
}

Rule: Use the functional form setX(prev => โ€ฆ) when the new state depends on the previous state.

๐Ÿ’ป Code Example โ€” Don't Mutate State

// โŒ wrong โ€” React doesn't detect the change
const addItem = (item) => {
  state.items.push(item);
  setItems(state.items);          // same reference โ†’ no re-render!
};

// โœ… right โ€” create a new array
const addItem = (item) => {
  setItems(prev => [...prev, item]);
};

// โœ… for objects
setUser(prev => ({ ...prev, name: "New" }));

๐Ÿ’ป Code Example โ€” useState with Complex State

function Form() {
  const [form, setForm] = useState({ name: "", email: "" });

  const update = (field) => (e) =>
    setForm(prev => ({ ...prev, [field]: e.target.value }));

  return (
    <>
      <input value={form.name}  onChange={update("name")}  />
      <input value={form.email} onChange={update("email")} />
    </>
  );
}

For complex state shapes, consider useReducer:

const [state, dispatch] = useReducer(reducer, initialState);
dispatch({ type: "UPDATE_FIELD", field: "name", value: "Soumya" });

๐Ÿ’ป Code Example โ€” Props Drilling Problem

function App() {
  const [theme, setTheme] = useState("light");
  return <Page theme={theme} />;
}
function Page({ theme }) { return <Sidebar theme={theme} />; }
function Sidebar({ theme }) { return <Menu theme={theme} />; }
function Menu({ theme }) { return <span>{theme}</span>; }
// theme is "drilled" through three components that don't use it.
// Solution: Context API (Chapter 18).

๐ŸŽฏ Likely Interview Questions

  1. Difference between props and state.
  2. Can a component change its own props? โ€” No; props are immutable inside the receiver.
  3. What is lifting state up?
  4. Why use the functional form of setState? โ€” When new state depends on the previous, the variable in closure may be stale.
  5. Why immutability for state? โ€” React uses reference equality (prev !== next) to decide whether to re-render.

โ† Functional Components | Index | Next: useEffect โ†’