Skip to solution
easyPhone Screen

How do you pass data between components in React?

803 views
01

Understand the problem

Question presented to candidate: "Walk me through the ways data moves between components in React — parent to child, child to parent, and between two siblings."

What a strong answer should cover:

  • Parent to child: props. The default, and read-only.
  • Child to parent: a callback passed down as a prop. Data still flows one way; the child invokes a function it was given.
  • Sibling to sibling: lift state up to the nearest common ancestor and pass it down to both.
  • Deep trees: Context, to avoid prop drilling — but note it is not a state manager, and every consumer re-renders when the value changes.
  • Genuinely global or server state: a store (Redux, Zustand, Jotai) or a data library (TanStack Query, SWR). Server state is a different problem from UI state.
  • Composition (children) as the underrated alternative to Context — often it removes the drilling entirely without any new machinery.
  • The judgement point: choose the narrowest mechanism that works; reaching for Context or Redux too early is the common mistake.
  • Refs and imperative handles exist for the rare escape-hatch case.

Clarifying questions expected:

  • "How far apart are these components in the tree?"
  • "Is this server data or UI state?" — they call for different tools.
  • "How often does it change?" — a frequently-changing Context value is a performance problem.

Code / implementation expected: Yes — lifting state up between two siblings is the canonical thing to write.

propsdata flowcomponent communicationcontext api
02

Attempt it yourself

Sketch your approach before reading the solution — that's what interviews test.

Nudge consolestandby

Stuck? Beam a request up — the console returns a conceptual nudge that guides your logic without spoiling the implementation.

03

Study the solution

Target Audience: Engineers preparing for React interviews — assumes props and state basics. Difficulty: Easy to Medium

How to read this doc: Concepts are explained in plain language first, then tagged with 📌 Interview term:. The composition measurement referenced in section 6 was produced b

Solution ready — 2 min read

Classified // press E to declassify

04

Explore the playground snippets

Lifting state up so two siblings stay in sync
Run Playground
import { useState } from "react";

// Sibling A — receives the value. It has no state of its own and no idea
// that another component exists.
function TemperatureInput({ scale, value, onChange }) {
  return (
    <label style={{ display: "block", marginBottom: 10 }}>
      Temperature in {scale === "c" ? "Celsius" : "Fahrenheit"}:{" "}
      <input
        value={value}
        onChange={(e) => onChange(scale, e.target.value)}
        style={{ width: 90 }}
      />
    </label>
  );
}

// Sibling B — reads the same lifted state, derived differently.
function BoilingVerdict({ celsius }) {
  if (Number.isNaN(celsius)) return <p style={{ color: "#888" }}>Enter a number.</p>;
  return <p><strong>{celsius >= 100 ? "The water would boil." : "The water would not boil."}</strong></p>;
}

const toC = (f) => ((f - 32) * 5) / 9;
const toF = (c) => (c * 9) / 5 + 32;
const round = (n) => (Number.isNaN(n) ? "" : String(Math.round(n * 1000) / 1000));

export default function App() {
  // The state lives in the nearest COMMON ANCESTOR of the components that
  // need it. Neither sibling owns it; neither talks to the other.
  const [temperature, setTemperature] = useState("22");
  const [scale, setScale] = useState("c");

  // The single callback both inputs share — this is the "up" direction.
  const handleChange = (whichScale, nextValue) => {
    setScale(whichScale);
    setTemperature(nextValue);
  };

  const parsed = parseFloat(temperature);
  const celsius = scale === "f" ? toC(parsed) : parsed;
  const fahrenheit = scale === "c" ? toF(parsed) : parsed;

  return (
    <div style={{ padding: 24, fontFamily: "system-ui", lineHeight: 1.6, maxWidth: 380 }}>
      <h3>Two inputs, one source of truth</h3>
      <TemperatureInput scale="c" value={scale === "c" ? temperature : round(celsius)} onChange={handleChange} />
      <TemperatureInput scale="f" value={scale === "f" ? temperature : round(fahrenheit)} onChange={handleChange} />
      <BoilingVerdict celsius={celsius} />
      <p style={{ color: "#666", fontSize: 13 }}>
        Type in either box and the other follows. The inputs never communicate —
        they both read from, and write to, the parent that owns the value.
      </p>
    </div>
  );
}
05

Join the discussion

Discussion (0)

Sign in to join the discussion.

No responses yet. Be the first to share what you think.

Transmission complete // awaiting log

KEEP THE
STREAK ALIVE.

Dossier 11 of 119 decoded in the React.js track. One more won't hurt.

Back to track