Skip to the solution
MediumMachine Coding12 min read

Build a Toast Notification system

380 views

The problem

Question presented to candidate: "Our app shows success and error messages in five different ways. Build us one toast notification system: any component should be able to call something like toast.success('Saved'), toasts stack in a corner, close on their own after a few seconds, and can be closed by hand."

Requirements:

  • An app-wide API: toast(message, options), toast.success, toast.error, toast.info, and toast.dismiss(id) / toast.dismiss() for all. Each call returns the new toast id.
  • Toasts stack in a fixed corner, newest first, rendered outside the normal page flow (a portal or equivalent).
  • Each toast closes itself after its duration (3 s for success and info, 5 s for errors); duration: 0 makes it sticky.
  • A close button on every toast; timers are cleaned up when a toast closes early or the app unmounts.
  • Accessible: an always-present live region, role="status" for normal toasts and role="alert" for errors, a labelled close button.

What a strong answer should cover:

  • Where the state lives (one list in a provider or service) and why the API object is stable, so callers do not re-render when toasts change.
  • Who owns each timer, and the cleanup that stops a removed toast from firing later (and survives React StrictMode).
  • Why the stack is rendered at the document body (portal, Teleport, or moving the host element) and positioned with position: fixed.
  • Live region rules: the region must exist before content is added; status versus alert and when to use each.
  • Sensible extensions: a max-visible queue, pause on hover, deduplication, promise toasts.

Clarifying questions expected:

  • "Should errors stay until dismissed, or close on a timer like the rest?"
  • "Is there a limit on how many toasts show at once, or do they stack freely?"
  • "Do toasts need to be raised from outside components, for example from an API helper?"

Code / implementation expected: Yes. A provider or service with the toast API, a viewport component, and a toast item with its own timer and close button.

  • React
  • Timers
  • Queue

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read ยท 10 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import { ToastProvider, useToast } from "./src/components/ToastProvider";

function Demo() {
  const toast = useToast();
  return (
    <main className="demo">
      <h1>Toast notifications</h1>
      <p>
        Any component can call the toast API. Success and info close after 3 s,
        errors after 5 s.
      </p>
      <div className="buttons">
        <button
          data-testid="btn-success"
          onClick={() => toast.success("Profile saved")}
        >
          Success
        </button>
        <button
          data-testid="btn-error"
          onClick={() => toast.error("Upload failed. Try again.")}
        >
          Error
        </button>
        <button
          data-testid="btn-info"
          onClick={() => toast.info("New version available")}
        >
          Info
        </button>
        <button
          data-testid="btn-sticky"
          onClick={() => toast.info("You are offline", { duration: 0 })}
        >
          Sticky
        </button>
        <button data-testid="btn-clear" onClick={() => toast.dismiss()}>
          Dismiss all
        </button>
      </div>
    </main>
  );
}

export default function App() {
  return (
    <ToastProvider>
      <Demo />
    </ToastProvider>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 60 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextMedium

Build a Multi-step Form (wizard)

Continue