Skip to solution
mediumFrontend

Describe the React component lifecycle.

1.0k views
01

Understand the problem

Question presented to candidate: "Walk me through a component's lifecycle in a function component. What runs, and in what order?"

What a strong answer should cover:

  • Three phases: mount, update, unmount — the class method names map onto hooks, they were not replaced by something conceptually different.
  • Mount: render → layout effects → browser paints → passive effects. useLayoutEffect runs before paint, useEffect after.
  • Update: render → the previous layout effect's cleanup → the new layout effect → the previous passive cleanup → the new passive effect. Cleanup of the old always precedes setup of the new, per hook.
  • Unmount: cleanups only, layout before passive.
  • An effect's cleanup is not just "on unmount" — it runs before every re-run, which is what makes subscriptions and timers safe.
  • useEffect with [] is not exactly componentDidMount: in StrictMode development React mounts, unmounts and remounts, so it runs twice. That is a test of your cleanup, not a bug.
  • There is no lifecycle hook for "props changed" — you express that as a dependency array, or derive the value during render.
  • The render phase must be pure; anything with a side effect belongs in an effect.

Clarifying questions expected:

  • "Function components or class components?" — the class names still come up in interviews.
  • "Do you need this before the browser paints?" — that is the useLayoutEffect question.

Code / implementation expected: Optional. A component that logs each phase makes the ordering concrete.

lifecyclemountingupdatingunmounting
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 hooks basics. Difficulty: Medium

How to read this doc: Concepts are explained in plain language first, then tagged with 📌 Interview term:. Every ordering below is executed output from React 19.2.8, not a description — t

Solution ready — 2 min read

Classified // press E to declassify

04

Explore the playground snippets

A component that logs every phase as you mount, update and unmount it
Run Playground
import { useState, useEffect, useLayoutEffect, StrictMode } from "react";

// Logs are pushed into a module-level array and read by the parent, so logging
// never schedules a render of its own.
const LOG = [];
const say = (s) => LOG.push(s);

function Tracked({ n }) {
  say("render n=" + n);

  useLayoutEffect(() => {
    say("  layout effect n=" + n + "  (DOM updated, before paint)");
    return () => say("  layout CLEANUP n=" + n);
  }, [n]);

  useEffect(() => {
    say("  effect n=" + n + "  (after paint)");
    return () => say("  effect CLEANUP n=" + n);
  }, [n]);

  return <span style={{ fontSize: 13 }}>value: {n}</span>;
}

export default function App() {
  const [n, setN] = useState(1);
  const [mounted, setMounted] = useState(true);
  const [strict, setStrict] = useState(false);
  const [, refresh] = useState(0);

  const show = () => refresh((v) => v + 1);
  const child = mounted ? <Tracked key={strict ? "s" : "n"} n={n} /> : null;

  return (
    <div style={{ padding: 24, fontFamily: "system-ui", lineHeight: 1.6, maxWidth: 540 }}>
      <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 10 }}>
        <button onClick={() => { setN((v) => v + 1); setTimeout(show, 0); }}>update prop</button>
        <button onClick={() => { setMounted((m) => !m); setTimeout(show, 0); }}>
          {mounted ? "unmount" : "mount"}
        </button>
        <button onClick={() => { setStrict((s) => !s); setTimeout(show, 0); }}>
          StrictMode: {strict ? "on" : "off"}
        </button>
        <button onClick={() => { LOG.length = 0; show(); }}>clear log</button>
      </div>

      <div style={{ border: "1px solid #ddd", borderRadius: 8, padding: 12, marginBottom: 10 }}>
        {strict ? <StrictMode>{child}</StrictMode> : child}
        {!mounted && <em style={{ fontSize: 13, color: "#999" }}>(unmounted)</em>}
      </div>

      <pre style={{ background: "#f6f6f8", padding: 10, borderRadius: 8, fontSize: 12, minHeight: 150, overflowX: "auto" }}>
{LOG.length ? LOG.join("\n") : "press a button, then read the order"}
      </pre>

      <p style={{ fontSize: 13, color: "#666" }}>
        Press "update prop" and read the order: render, then the OLD layout
        cleanup, the new layout effect, the OLD passive cleanup, the new passive
        effect. Cleanup before setup, layout pair before passive pair. Then turn
        StrictMode on and watch the mount run effect, cleanup, effect — that is
        React testing whether your teardown is complete.
      </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 38 of 119 decoded in the React.js track. One more won't hurt.

Back to track