Back

Like Dislike I

easy

Streak

0 days

Progress

0%

Submitted

0

Like Dislike I

React30 mineasyFreeNew

Prompt

The Like/Dislike button pair is a fundamental UI pattern found on YouTube, Reddit, and every social platform. Building it correctly requires handling mutually exclusive toggle state: liking should un-dislike, disliking should un-like, and clicking an active button should deactivate it.

Build a LikeDislike component that shows a thumbs-up count, a thumbs-down count, and two interactive buttons. The interaction rules are: clicking Like toggles it (and removes Dislike if active). Clicking Dislike toggles it (and removes Like if active). Counts update accordingly.

This question tests your ability to model mutually exclusive UI state cleanly without complex conditionals. The ideal solution uses a single state variable (not two booleans) to represent three possible states: liked, disliked, or neutral.

Requirements

  • →Like and Dislike are mutually exclusive — only one can be active
  • →Clicking an active button deactivates it (toggle off)
  • →Like count increments when liked, decrements when un-liked
  • →Dislike count increments when disliked, decrements when un-disliked
  • →Visual distinction between active and inactive state
  • →Accessible button labels with aria-pressed
Example
Loading preview...
For the best coding experience, we recommend using a desktop device.
Preparing Sandbox...
Premium interview report

What interviewers score in this build

Use this before reading the code. It tells you what to say, what to test, and where machine-coding candidates usually lose points.

Interview signals

  • Tri-state model: Single 'liked'|'disliked'|null state instead of two booleans
  • Toggle logic: Clicking active button deactivates it (sets to null)
  • Derived counts: Counts computed from state, not stored separately
  • Mutual exclusivity: Like removes dislike and vice versa automatically

Time checkpoints

  1. 1

    0–3 min: Explain tri-state approach vs two booleans

  2. 2

    3–7 min: Set up vote state and toggle handler

  3. 3

    7–11 min: Derive like/dislike counts from state

  4. 4

    11–15 min: Apply active styling to buttons

Edge-case checklist

Empty data and first-load state
Slow network, failed request, and retry path
Keyboard navigation and focus movement
Large input size, re-render pressure, and cleanup

Common mistakes

  • Starting with JSX before naming state and events.
  • Ignoring accessibility until the final minute.
  • Over-building abstractions instead of finishing the required behavior.
  • Failing to narrate trade-offs while coding.
SolutionRead-only · Live Preview

Technical Explanation

Why This Question Exists

Like/Dislike tests whether you instinctively reach for the simplest correct state model. Most candidates use two boolean flags — isLiked and isDisliked. That works, but it introduces a class of bugs: you must always remember to clear one when setting the other. Miss that in one place and you get a state where both appear active simultaneously.

The Wrong Approach: Two Booleans

// ❌ WRONG — requires manual synchronisation
const [isLiked, setIsLiked] = useState(false);
const [isDisliked, setIsDisliked] = useState(false);

const handleLike = () => {
  setIsLiked(l => !l);
  setIsDisliked(false); // easy to forget this line
};
const handleDislike = () => {
  setIsDisliked(d => !d);
  setIsLiked(false); // and this one
};

This works when you remember to clear the other flag. But it's fragile — two independent state updates means React could in theory render a frame between them with both true. More importantly, it violates the single-source-of-truth principle.

The Right Approach: Tri-State Enum

// ✅ CORRECT — single source of truth, mutual exclusivity is free
type Vote = 'liked' | 'disliked' | null;
const [vote, setVote] = useState<Vote>(null);

const toggle = (val: Vote) => setVote(v => v === val ? null : val);
// Clicking Like when already liked → null (deactivate)
// Clicking Like when disliked → 'liked' (automatically clears disliked)
// Clicking Like when neutral → 'liked'

The mutual exclusivity is now structural — there is literally no state where both are active. The toggle logic fits in one line. This pattern is called a discriminated union or enum-style state.

Deriving Counts — never store what you can compute

// ❌ WRONG — counts can drift out of sync with vote state
const [likes, setLikes] = useState(142);
const [dislikes, setDislikes] = useState(8);

// ✅ CORRECT — counts derived from vote state, always in sync
const likes    = initialLikes    + (vote === 'liked'    ? 1 : 0);
const dislikes = initialDislikes + (vote === 'disliked' ? 1 : 0);

If you store counts in state, you have to update three pieces of state on every click (vote, likes, dislikes). They can drift out of sync if an update is missed. Derived values are always correct because they're computed fresh on every render.

ℹ Interview Tip

Say: "I use a tri-state enum ('liked' | 'disliked' | null) rather than two booleans. This makes mutual exclusivity structurally guaranteed — there's no code path where both can be true. I derive the counts from this state rather than storing them separately, so they're always consistent."

Accessibility — aria-pressed

<button
  aria-pressed={vote === 'liked'}
  aria-label="Like this post"
  onClick={() => toggle('liked')}
>
  👍 {likes}
</button>

aria-pressed is the semantic attribute for toggle buttons. Screen readers announce "Like button, pressed" when active and "Like button, not pressed" when inactive. Without it, the visual active state is completely invisible to assistive technology users.

⚠ Common Pitfall: Using checkbox semantics for toggle buttons

Developers sometimes reach for <input type="checkbox"> for toggle buttons to get built-in aria semantics. But a checkbox announces "checked/unchecked" — a Like button should announce "pressed/not pressed". Use <button aria-pressed> for toggle actions.

Interview Criteria

Tri-state model

Single 'liked'|'disliked'|null state instead of two booleans

Toggle logic

Clicking active button deactivates it (sets to null)

Derived counts

Counts computed from state, not stored separately

Mutual exclusivity

Like removes dislike and vice versa automatically

Accessibility

aria-pressed reflects active state on each button

Time Checkpoints

0–3 min

0–3 min: Explain tri-state approach vs two booleans

3–7 min

3–7 min: Set up vote state and toggle handler

7–11 min

7–11 min: Derive like/dislike counts from state

11–15 min

11–15 min: Apply active styling to buttons

15–19 min

15–19 min: Add aria-pressed for accessibility

19–25 min

19–25 min: Test all transitions: like→dislike→neutral→like

Streak

0 days

Last active: Sign in to track

Progress

0%

0/0 solved

Submitted

0

Solutions pushed to review history.