Propagation and defaults

See why a click on Play also hits the card, and how to stop a link leaving the page.

The card itself can have an onClick. Play sits on that card.

A click travels up

Play is inside the card. A click starts at Play, then travels up to the <article>.

import "./styles.css";
import ShowCard from "./ShowCard";

export default function App() {
  return (
    <div className="page">
      <ShowCard
        title="The Bear"
        year={2022}
        genre="Drama"
        rating={8.6}
        still="still-warm"
      />
    </div>
  );
}

Press Play. The console reads play: The Bear, then card: The Bear. Press the gradient or the title: only card: The Bear.

The click starts where you pressed, then runs every parent handler too. That journey is called bubbling.

stopPropagation

React hands the handler an event object. Call event.stopPropagation() and the click stops at Play.

import "./styles.css";
import ShowCard from "./ShowCard";

export default function App() {
  return (
    <div className="page">
      <ShowCard
        title="The Bear"
        year={2022}
        genre="Drama"
        rating={8.6}
        still="still-warm"
      />
    </div>
  );
}

Press Play. The console reads only play: The Bear. Press the gradient or the title, and you still get card: The Bear.

preventDefault

A link has a default of its own: the browser follows href. That takes the preview to TVMaze, and the card vanishes.

import "./styles.css";
import ShowCard from "./ShowCard";

export default function App() {
  return (
    <div className="page">
      <ShowCard
        title="The Bear"
        year={2022}
        genre="Drama"
        rating={8.6}
        still="still-warm"
      />
    </div>
  );
}

Press Open on TVMaze. The preview leaves the watchlist.

return false does nothing in React. Call event.preventDefault() on the event object instead.

import "./styles.css";
import ShowCard from "./ShowCard";

export default function App() {
  return (
    <div className="page">
      <ShowCard
        title="The Bear"
        year={2022}
        genre="Drama"
        rating={8.6}
        still="still-warm"
      />
    </div>
  );
}

Press Open on TVMaze. The console reads open: The Bear, and the card stays. You also see card: The Bear. preventDefault does not stop bubbling.

Common mistakes

  • Forgetting Play sits inside the card. A click on Play runs Play's handler, then the card's, unless you call event.stopPropagation().
  • return false. It does nothing in React, so call event.preventDefault() to keep the preview on the cards.
  • preventDefault when you meant stopPropagation. The first stops the browser's default; the second stops the click travelling up.

Exercise

Play also logs the card, and Open on TVMaze leaves the preview.

Fix both. Press Play on The Bear. The console reads only:

play: The Bear

Press Open on TVMaze on The Bear. The three cards stay on screen, and the console reads:

open: The Bear
card: The Bear

Hint: Play needs event.stopPropagation(). The link's return false does nothing; use event.preventDefault().

import "./styles.css";
import ShowCard from "./ShowCard";

export default function App() {
  return (
    <div className="page">
      <ShowCard
        title="The Bear"
        year={2022}
        genre="Drama"
        rating={8.6}
        still="still-warm"
      />
      <ShowCard
        title="Severance"
        year={2022}
        genre="Thriller"
        rating={8.7}
        still="still-cold"
      />
      <ShowCard
        title="Andor"
        year={2022}
        genre="Sci-Fi"
        rating={8.4}
        still="still-dusty"
      />
    </div>
  );
}