Fanatics Markets Mock Interview

Structured like a real pair-programming interview. Each scenario has interview flow, collapsible solutions, and in-depth follow-up answers.

Format (60 min)
Interviewer Protocol (Applied To Every Scenario)
Mandatory flow: clarifying questions first, then state strategy, then source-of-truth vs derived state, then implementation approach, then edge-case/scale/product challenge questions.
Post-scenario debrief (mandatory): what was tested, what strong candidates say, what weak candidates miss, relevant React concepts, and relevant product-engineering concepts.
React Concepts You Should Explain Clearly
useState:
Use it for local, mutable UI state such as form inputs, selected filters, or submit status. State updates must be immutable because React re-renders based on reference changes. Good line to use: “I keep only source-of-truth values in state and avoid storing values that can be derived.”
useEffect:
Use it for side effects like fetching data, subscriptions, and timers. Explain dependency arrays clearly and call out cleanup to avoid memory leaks or setting state on unmounted components. Good line: “I clean up network requests/subscriptions in the effect return function to prevent stale updates.”
useMemo:
Use it to memoize expensive derived computations (for example large filter/sort transforms), not as a default wrapper for all values. Good line: “I use useMemo when recomputation cost is meaningful and dependencies are clear.”
Derived State:
Prefer deriving values like visibleMarkets from markets + controls during render (or with useMemo) instead of duplicating them in separate state. This avoids sync bugs and multiple sources of truth, especially with real-time updates.
Loading/Error States:
Model async state explicitly (for example idle/loading/success/error) so UI behavior is predictable. Show loading indicators, meaningful error text, and a retry path. Guard against stale responses when multiple requests overlap.
Optimistic UI:
Update UI immediately before server confirmation to improve responsiveness, then reconcile with server result. Include rollback on failure, pending markers, duplicate-submit prevention, and idempotency keys for safe retries.
Technical Functional (Pair Programming): Prep-Pack Alignment
What to expect (1 hour): A practical pair-programming session using real-world scenarios, not LeetCode-style puzzles.
Execution strategy: implement clean JavaScript logic first when appropriate, then map it clearly to React hooks/components and production patterns.
-Scenario 1: Search + Filter + Sort Markets
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Build a market-list data transformation layer for a prediction trading UI. I want you to support search, filtering, and sorting while keeping logic readable and testable. Explain your state strategy before coding, including what should be source-of-truth vs derived.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Business Context

Users need to quickly find tradable markets during high activity windows.

Starter Data
const markets = [
  { id: "m1", title: "Will Arsenal win the league?", probability: 0.72, volume: 120000, status: "open", updatedAt: "2026-05-01T10:00:00Z" }
];
Task Requirements
  • Search by title (case-insensitive).
  • Filter by status/category.
  • Sort by probability, volume, time.
  • Show empty state and loading/error states.
React Concepts To Mention
React concept to use: useState for controls (search, status, sortBy) and useMemo for derived visibleMarkets. Use this because filter/sort recomputes often; keep markets as source-of-truth and avoid duplicated derived state.
Clarifying Questions You Should Ask
Client-side or server-side sort/filter? Dataset size? Real-time updates? Should closed markets remain visible?
Follow-Up Prompts (Interviewer)
  • Use useMemo and explain why.
  • Explain why duplicated derived state is problematic.
  • Add retry and accessibility improvements.
+In-Depth Follow-Up Answers
Why useMemo?
Filtering and sorting are O(n log n) and run every render by default. In fast-updating UIs, this causes unnecessary CPU work and jank. useMemo constrains recalculation to dependency changes (markets, search, status, sortBy), improving responsiveness. I’d also mention that useMemo is an optimization, not correctness logic.
Why avoid duplicated derived state?
Keeping both markets and filteredMarkets in state introduces sync bugs, especially with websocket updates. If one updates and the other does not, UI diverges from truth. Deriving visible rows from source + UI controls removes that failure mode and simplifies reasoning and tests.
Accessibility improvements:
Use semantic controls (<label>, <select>, <button>), keyboard-focus styles, aria-live="polite" for async loading/error messages, explicit empty-state copy, and table headers with scope for screen readers.
+Full End-to-End Solution
function getSortConfig(sortBy = "updatedAt_desc") {
  const map = {
    volume_desc: { field: "volume", dir: -1 },
    volume_asc: { field: "volume", dir: 1 },
    probability_desc: { field: "probability", dir: -1 },
    probability_asc: { field: "probability", dir: 1 },
    updatedAt_desc: { field: "updatedAt", dir: -1 },
    updatedAt_asc: { field: "updatedAt", dir: 1 }
  };
  return map[sortBy] || map.updatedAt_desc;
}

function getVisibleMarkets(markets, { search = "", status = "all", sortBy = "updatedAt_desc" } = {}) {
  const term = search.trim().toLowerCase(); // Normalize search once for consistent matching.
  const normalizedStatus = status.trim().toLowerCase();
  const sort = getSortConfig(sortBy);

  return markets
    .filter(m => normalizedStatus === "all" || m.status.toLowerCase() === normalizedStatus) // Filter from source data; do not mutate source markets.
    .filter(m => m.title.toLowerCase().includes(term))
    .slice()
    .sort((a, b) => {
      const av = sort.field === "updatedAt" ? new Date(a.updatedAt).getTime() : a[sort.field];
      const bv = sort.field === "updatedAt" ? new Date(b.updatedAt).getTime() : b[sort.field];
      if (av === bv) return String(a.id).localeCompare(String(b.id)); // Deterministic tie-break prevents unstable list ordering.
      return (av - bv) * sort.dir;
    });
}

function getMarketListState({ markets, loading, error, filters }) {
  if (loading) return { type: "loading", message: "Loading markets..." };
  if (error) return { type: "error", message: error, canRetry: true };
  const rows = getVisibleMarkets(markets, filters);
  if (!rows.length) return { type: "empty", message: "No matching markets found." };
  return { type: "ready", data: rows };
}
+Scenario 2: Debounced Search + Stale Request Protection
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Search should call API, but not on every keystroke. Add debounce and ensure stale responses do not override newer input.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Example Inputs
const typedQueries = ["a", "ar", "ars", "arse", "arsen", "arsena", "arsenal"];
const debounceMs = 300;
Task Requirements
  • Debounce outbound requests.
  • Cancel or ignore stale in-flight responses.
  • Preserve loading/error state behavior.
React Concepts To Mention
React concept to use: useEffect for debounce timer + cleanup and request cancellation; pair with useRef request-id tracking to ignore stale responses.
+In-Depth Follow-Up Answers
Why debounce + stale guard:
Debounce limits request volume; stale-response guard prevents race conditions where slower old responses overwrite newer intent.
+Full End-to-End Solution
function debounce(fn, wait = 300) { // Debounce limits request volume while user is typing.
  let timerId = null;
  return (...args) => {
    clearTimeout(timerId);
    timerId = setTimeout(() => fn(...args), wait);
  };
}

function createDebouncedMarketSearch({ fetchMarkets, onStateChange, debounceMs = 300 }) {
  let requestCounter = 0;
  let activeController = null;
  let latestQuery = "";

  const state = { query: "", data: [], loading: false, error: null };
  const setState = patch => { Object.assign(state, patch); onStateChange({ ...state }); };

  async function runSearch(query) {
    latestQuery = query;
    const trimmed = query.trim();
    if (!trimmed) {
      if (activeController) activeController.abort(); // Cancel stale in-flight requests to avoid race overwrite.
      setState({ query, data: [], loading: false, error: null });
      return;
    }

    if (activeController) activeController.abort();
    activeController = new AbortController();

    const currentId = ++requestCounter; // Request ordering guard ensures latest intent wins.
    setState({ query, loading: true, error: null });

    try {
      const data = await fetchMarkets(trimmed, { signal: activeController.signal });
      if (currentId !== requestCounter || query !== latestQuery) return;
      setState({ data, loading: false, error: null });
    } catch (err) {
      if (err?.name === "AbortError" || currentId !== requestCounter) return;
      setState({ loading: false, error: err?.message || "Search failed" });
    }
  }

  const debouncedSearch = debounce(runSearch, debounceMs);
  return {
    search: debouncedSearch,
    retry: () => runSearch(state.query),
    cancel: () => activeController && activeController.abort(),
    getState: () => ({ ...state })
  };
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.
+Scenario 3: Trade History + Portfolio Holdings
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Given raw trades, compute holdings per market and return a sorted portfolio summary. I’m evaluating correctness under invalid data, duplicate events, and edge cases like overselling. Talk through your assumptions before implementation.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Task Requirements
  • Ignore cancelled trades.
  • Buy adds, sell subtracts.
  • Group by market and calculate cost basis.
  • Sort by largest position.
  • Handle invalid or duplicate trades.
React Concepts To Mention
React concept to use: useMemo around a pure calculateHoldings function. Use this because holdings transforms can be expensive and should remain testable and deterministic.
Example Inputs
const trades = [
  { id: "t1", marketId: "m1", marketTitle: "Will Arsenal win the league?", side: "buy", quantity: 10, price: 0.45, status: "filled", timestamp: "2026-05-01T10:00:00Z" },
  { id: "t2", marketId: "m1", marketTitle: "Will Arsenal win the league?", side: "sell", quantity: 4, price: 0.55, status: "filled", timestamp: "2026-05-02T10:00:00Z" },
  { id: "t3", marketId: "m2", marketTitle: "Will BTC close above $100k?", side: "buy", quantity: 8, price: 0.50, status: "cancelled", timestamp: "2026-05-03T10:00:00Z" }
];
Follow-Ups
What if user sells more than owned? How keep this pure/testable? How handle out-of-order real-time events? How would you calculate realised vs unrealised PnL given current market prices?
+In-Depth Follow-Up Answers
Oversell handling:
Define policy explicitly: reject trade, clamp to zero, or allow short positions. In consumer prediction markets, rejection with explicit error is usually safest. Logic should return both holdings and validation issues so UI can surface anomalies.
Pure + testable design:
Extract transformation into a pure function calculateHoldings(trades). Keep hook thin: useMemo(() => calculateHoldings(trades), [trades]). Unit-test pure function with fixtures: cancelled trades, duplicates, invalid quantity, oversell.
Real-time/out-of-order events:
Include event timestamp/version. Apply only if event is newer than last applied event per trade/market. Track processed event IDs for idempotency. This prevents replay and stale application under reconnects.
Realised vs unrealised PnL:
Clarify product definition first. Cost basis, realised PnL, and unrealised value vary by settlement model and fill rules. State assumptions explicitly before implementing formulas.
+Full End-to-End Solution
function calculateHoldings(trades, currentPriceByMarket = {}) { // Pure aggregation function: unit-test this independently.
  const seen = new Set();
  const byMarket = new Map();
  const issues = [];

  for (const t of trades) {
    if (!t || seen.has(t.id)) { if (t?.id) issues.push(`duplicate:${t.id}`); continue; } // Idempotency/duplicate protection for repeated events.
    seen.add(t.id);
    if (t.status === "cancelled") continue; // Cancelled trades are excluded from holdings math.
    if (!["buy", "sell"].includes(t.side) || !Number.isFinite(t.quantity) || t.quantity <= 0 || !Number.isFinite(t.price)) {
      issues.push(`invalid:${t.id}`);
      continue;
    }

    const row = byMarket.get(t.marketId) || {
      marketId: t.marketId,
      marketTitle: t.marketTitle,
      quantity: 0,
      costBasis: 0,
      realizedPnl: 0
    };

    if (t.side === "buy") {
      row.quantity += t.quantity;
      row.costBasis += t.quantity * t.price;
    } else {
      if (row.quantity < t.quantity) {
        issues.push(`oversell:${t.id}`); // Oversell is explicit validation, not silent correction.
        continue;
      }
      const avgCost = row.quantity ? row.costBasis / row.quantity : 0;
      row.quantity -= t.quantity;
      row.costBasis -= avgCost * t.quantity;
      row.realizedPnl += (t.price - avgCost) * t.quantity;
    }

    byMarket.set(t.marketId, row);
  }

  const holdings = Array.from(byMarket.values()).map(h => {
    const mark = currentPriceByMarket[h.marketId];
    const unrealizedPnl = Number.isFinite(mark) ? (mark * h.quantity) - h.costBasis : null;
    return { ...h, unrealizedPnl };
  }).sort((a, b) => b.quantity - a.quantity);

  return { holdings, issues };
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.
+Scenario 4: Fetch + Loading + Error + Retry
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Implement robust async data loading for markets. Your solution should clearly model loading/error states, avoid stale updates, and provide retry behavior. I care about race-condition handling and cleanup strategy.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Task Requirements
  • Fetch markets on mount/query change.
  • Show loading and error states.
  • Add retry button.
  • Avoid stale updates and cleanup requests.
React Concepts To Mention
React concept to use: useEffect for request lifecycle, useState for loading/error/data, and cleanup with AbortController to prevent stale updates.
Example Inputs
const query = "arsenal";
const previousState = { data: [], loading: false, error: null };
// expected API shape:
// [{ id, title, probability, volume, status, updatedAt }]
+In-Depth Follow-Up Answers
Retry button:
Retry should reuse the same fetch pathway to avoid duplicated logic. Keep button disabled while loading to prevent request storms. Optionally exponential backoff for repeated failures.
Stale fetches:
When query changes rapidly, earlier requests can finish later and overwrite newer data. Use abort signals or a request sequence ID check before state commit. This is a common race condition interviewers probe.
Prevent duplicate requests:
Debounce input-driven queries, disable retry during active request, and dedupe by query key (libraries like React Query/SWR handle this well).
+Full End-to-End Solution
async function fetchMarkets(query, { signal } = {}) { // Fetch wrapper isolates transport concerns from UI state logic.
  const res = await fetch(`/api/markets?q=${encodeURIComponent(query)}`, { signal });
  if (!res.ok) throw new Error(`Request failed: ${res.status}`);
  return res.json();
}

function createMarketsLoader() {
  let requestId = 0;
  let controller = null;

  return async function load(query, prev = { data: [], loading: false, error: null }) {
    if (controller) controller.abort();
    controller = new AbortController();
    const current = ++requestId; // Sequence id prevents stale responses replacing fresh state.
    const next = { ...prev, loading: true, error: null };

    try {
      const data = await fetchMarkets(query, { signal: controller.signal });
      if (current !== requestId) return prev;
      return { data, loading: false, error: null };
    } catch (e) {
      if (e.name === "AbortError" || current !== requestId) return prev; // Ignore aborted/stale outcomes to preserve correctness.
      return { ...next, loading: false, error: e.message };
    }
  };
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.
+Scenario 5: Optimistic UI Trade Submission
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Implement a trade submit flow that feels fast for users by using optimistic updates. Show validation, pending UI behavior, rollback on failure, and duplicate-submit prevention. Explain how idempotency would fit in production.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Task Requirements
  • Validate quantity/price.
  • Disable submit while pending.
  • Optimistically render trade.
  • Rollback on failure and prevent duplicates.
React Concepts To Mention
React concept to use: useState (or useReducer if flow grows) for pending/error/trade rows, with optimistic update + rollback. Disable submit while pending to prevent duplicates.
Example Inputs
const tradeInput = { marketId: "m1", side: "buy", quantity: 5, price: 0.62 };
// optimistic row shape:
// { id: "client-request-id", marketId, side, quantity, price, status: "pending" }
Follow-Ups
How handle price changes before confirmation? Where does idempotency fit? How communicate pending/failed states?
+In-Depth Follow-Up Answers
Price changed before confirmation:
Server should validate against current market price/slippage limits and reject if outside tolerance. UI then transitions optimistic row from pending to failed with reason and quick retry/edit path.
Idempotency:
Include client-generated request ID. If user retries due to timeout, server treats repeated ID as same intent and returns existing result rather than creating duplicate trades.
Pending/failed UX:
Use explicit status badges (Pending, Confirmed, Failed), disable duplicate submit actions, and provide actionable error copy. Keep optimistic row visible on failure until user dismisses, so they understand what happened.
Why addPendingTrade, replaceTrade, removeTrade are not inside the core snippet:
The main snippet intentionally isolates optimistic-flow logic. Those functions are infrastructure-level state handlers that differ by app architecture (local React state, reducer, Zustand/Redux store, or React Query cache). Passing them in as dependencies keeps the flow function reusable, easier to unit test, and decoupled from a specific state management choice.
+Full End-to-End Solution
function validateTradeInput({ quantity, price }) { // Validate early before optimistic mutation.
  if (!Number.isFinite(quantity) || quantity <= 0) return { ok: false, message: "Quantity must be greater than 0" };
  if (!Number.isFinite(price) || price < 0 || price > 1) return { ok: false, message: "Price must be between 0 and 1" };
  return { ok: true };
}

function addPendingTrade(prev, pending) { return [pending, ...prev]; }
function replaceTrade(prev, tempId, confirmed) { return prev.map(t => (t.id === tempId ? confirmed : t)); }
function removeTrade(prev, tempId) { return prev.filter(t => t.id !== tempId); }

async function submitTradeOptimistically(input, handlers) {
  const { readTrades, writeTrades, apiSubmit } = handlers;
  const check = validateTradeInput(input);
  if (!check.ok) throw new Error(check.message);

  const id = crypto.randomUUID();
  const pending = { id, ...input, status: "pending" }; // Optimistic row gives immediate user feedback.
  writeTrades(addPendingTrade(readTrades(), pending));

  try {
    const confirmed = await apiSubmit({ ...input, clientRequestId: id });
    writeTrades(replaceTrade(readTrades(), id, { ...confirmed, status: "confirmed" }));
    return confirmed;
  } catch (e) {
    writeTrades(removeTrade(readTrades(), id)); // Rollback on failure keeps UI consistent with server truth.
    throw e;
  }
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.
+Scenario 6: Real-Time Market Updates
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Apply incoming market updates safely in a real-time feed. Ignore unknown IDs and stale events, preserve immutable updates, and explain ordering/conflict assumptions for near-simultaneous messages.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Task Requirements
  • Update matching market only.
  • Ignore unknown IDs.
  • Ignore stale timestamps.
  • Keep immutable updates and preserve existing fields.
React Concepts To Mention
React concept to use: functional setState(prev => ...) with immutable updates. Use this because real-time events can arrive quickly and must apply to freshest state.
Example Inputs
const markets = [
  { id: "m1", title: "Will Arsenal win the league?", probability: 0.62, volume: 125000, updatedAt: "2026-05-01T10:00:00Z" },
  { id: "m2", title: "Will BTC close above $100k?", probability: 0.48, volume: 250000, updatedAt: "2026-05-02T12:30:00Z" }
];

const update = {
  marketId: "m1",
  probability: 0.67,
  volume: 130000,
  updatedAt: "2026-05-02T14:00:00Z"
};
+In-Depth Follow-Up Answers
WebSocket behavior:
Implement reconnect with backoff, snapshot re-sync after reconnect, and heartbeat monitoring. Real-time streams can drop; re-sync ensures local state consistency.
Simultaneous updates:
Use functional state updates so each event applies to latest state. Prefer server sequence/version plus timestamp to deterministically resolve conflicts.
Testing stale handling:
Unit-test applyUpdate with newer/older/equal timestamps and unknown IDs. Add integration test for rapid event bursts to ensure no mutation and stable final state.
Production monitoring:
Track dropped stale events, unknown market IDs, socket reconnect rate, message lag, and divergence checks between periodic snapshot and client state.
+Full End-to-End Solution
function applyUpdate(markets, update) { // Immutable patch keeps state transitions predictable.
  return markets.map(m => {
    if (m.id !== update.marketId) return m; // Ignore unknown/non-target rows to avoid accidental writes.
    const prevTs = new Date(m.updatedAt).getTime();
    const nextTs = new Date(update.updatedAt).getTime();
    if (Number.isFinite(prevTs) && Number.isFinite(nextTs) && nextTs < prevTs) return m; // Drop stale updates so state never regresses.
    return { ...m, ...update, id: m.id }; // Immutable patch preserves unchanged fields.
  });
}

function applyBatchUpdates(markets, updates) {
  let next = markets;
  for (const u of updates) {
    if (!next.some(m => m.id === u.marketId)) continue;
    next = applyUpdate(next, u);
  }
  return next;
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.
+Scenario 7: Feature Flags / A-B Test Rendering
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Render market UI variants based on feature flags without creating nested conditional chaos. Explain experiment metrics and rollback plan.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Example Inputs
const flags = {
  newMarketCard: true,
  quickTrade: false,
  showProbabilityChart: true
};
Task Requirements
  • Render safely when a flag is missing.
  • Avoid deeply nested conditional rendering.
  • Explain A/B instrumentation and success criteria.
React Concepts To Mention
React concept to use: useMemo for normalized flag config and variant mapping. Use this to avoid nested conditionals and keep experiment logic centralized/rollback-friendly.
+In-Depth Follow-Up Answers
A/B structure:
Keep flag evaluation centralized (config layer), and keep UI components simple by mapping variants instead of condition ladders. This makes rollback and cleanup easier.
Success criteria:
Define primary metric (trade completion) and guardrail metrics (error rate, latency, abandonment) before launch. No metric plan means ambiguous experiment decisions.
+Full End-to-End Solution
function getFeatureConfig(flags = {}) { 
  return {
    newMarketCard: Boolean(flags.newMarketCard), // Safe fallback when flag payload is partial/missing.
    quickTrade: Boolean(flags.quickTrade),
    showProbabilityChart: Boolean(flags.showProbabilityChart)
  };
}

function getMarketPresentation(market, flags) {
  const cfg = getFeatureConfig(flags);
  return {
    cardVariant: cfg.newMarketCard ? "v2" : "v1",
    canQuickTrade: cfg.quickTrade && market.status === "open",
    showProbabilityChart: cfg.showProbabilityChart
  };
}

function getExperimentMetrics() { 
  return ["card_click_through", "quick_trade_submit_rate", "trade_completion_rate", "error_rate"];
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.
+Scenario 8: Pagination / Infinite Scroll
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Handle large market sets using pagination or load-more while preserving filter/sort/search state and avoiding duplicate fetches.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Example Inputs
const page = 1;
const pageSize = 20;
const filters = { status: "open", search: "arsenal", sortBy: "volume_desc" };
Task Requirements
  • Support next/prev or load-more behavior.
  • Preserve active filters while paging.
  • Prevent duplicate page fetches.
React Concepts To Mention
React concept to use: useState for page/filter controls and useMemo for paginated/filtered rows. This cleanly separates UI state from source data.
+In-Depth Follow-Up Answers
Scale trade-off:
Client-side paging is fine for small datasets. For large/real-time data, move filtering/sorting/paging server-side and keep frontend focused on view-state transitions.
+Full End-to-End Solution
function paginate(items, page = 1, pageSize = 20) { // Pagination math remains framework-agnostic and deterministic.
  const totalPages = Math.max(1, Math.ceil(items.length / pageSize));
  const safePage = Math.min(Math.max(page, 1), totalPages); // Clamp page index to valid bounds.
  const start = (safePage - 1) * pageSize; // Deterministic offset calculation for stable paging.

  return {
    rows: items.slice(start, start + pageSize),
    page: safePage,
    totalPages,
    hasNext: safePage < totalPages,
    hasPrev: safePage > 1
  };
}

function makeRequestKey({ page, pageSize, filters }) { 
  return JSON.stringify({ page, pageSize, filters });
}

function shouldFetchPage(cache, key) {
  return !cache.has(key);
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.
+Scenario 9: Market Resolution / Status Transition
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: A market transitions from resolving to resolved. Update UI, disable trading, and reconcile late/stale trade submissions correctly.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Example Inputs
const before = { id: "m1", status: "resolving", outcome: null };
const after = { id: "m1", status: "resolved", outcome: "YES" };
Task Requirements
  • Disable trading for non-open markets.
  • Display resolved state and outcome.
  • Prevent stale submissions; reconcile backend rejection.
React Concepts To Mention
React concept to use: derived state via useMemo for canTrade/banner from market status, plus useState for submission errors to reconcile race-condition rejections.
+In-Depth Follow-Up Answers
Correctness model:
Disable actions immediately in UI for responsiveness, but backend remains source of truth. If client races and submits late, server rejects and client reconciles state/error message.
+Full End-to-End Solution
function canTrade(market) { 
  return market?.status === "open";
}

function applyMarketResolution(market, update) {
  if (market.id !== update.id) return market;
  return { ...market, status: update.status, outcome: update.outcome ?? market.outcome }; 
}

function getMarketUiState(market) {
  return {
    disabledTrading: !canTrade(market),
    resolvedBanner: market.status === "resolved" ? `Resolved: ${market.outcome}` : null
  };
}

function reconcileTradeSubmitError(err) {
  if (err?.code === "MARKET_CLOSED") return "Market just closed. Trade was not placed."; // Race-condition submit is reconciled with clear UX message.
  return "Trade failed. Please retry.";
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.
+Scenario 10: Watchlist / Favourites
Interviewer Task
Execution style: Implement in JavaScript first, then explain the React hook/component structure you would use in production.
Prompt: Implement watched-market toggles with optimistic behavior and rollback, then keep watchlist sorted by latest activity.
Interviewer-Led Flow (Use In Real Time)
Step 1 — Clarify first: What assumptions do you want to confirm before coding?
Step 2 — State strategy: Walk me through source-of-truth state vs derived state. What do you refuse to store directly, and why?
Step 3 — React mapping: If this were React, where would useState, useEffect, and useMemo fit? Where would you avoid useMemo as overkill?
Step 4 — Challenge questions: What happens at scale? What happens with out-of-order updates? Where can stale state or race conditions appear?
Step 5 — Product and UX: How do accessibility, resilience, and product behavior influence your implementation choices?
Step 6 — Testing: Which parts are pure unit tests vs integration tests? What are your highest-risk test cases?
Step 7 — Production bar: What would you change for production observability, rollbacks, and operational safety?
Example Inputs
const watchlistIds = ["m1", "m5"];
const toggleRequest = { marketId: "m2", watched: true };
Task Requirements
  • Toggle watched/unwatched state.
  • Persist via API or local storage.
  • Optimistic update with rollback on failure.
  • Sort watched items by latest activity.
React Concepts To Mention
React concept to use: useState for watchlist ids, optimistic toggle + rollback on failure, and useMemo to derive sorted watched markets from ids + source markets.
+In-Depth Follow-Up Answers
Optimistic rollback:
Apply toggle immediately for responsive UX, call persistence API, and revert prior value if request fails. This pattern mirrors optimistic trade submission but with simpler domain risk.
+Full End-to-End Solution
function toggleWatchlistId(ids, marketId) { // Toggle logic is pure and reversible.
  return ids.includes(marketId) ? ids.filter(id => id !== marketId) : [marketId, ...ids]; 
}

function sortWatchlist(markets, watchlistIds) {
  const set = new Set(watchlistIds);
  return markets
    .filter(m => set.has(m.id))
    .sort((a, b) => new Date(b.updatedAt) - new Date(a.updatedAt));
}

async function persistWatchlist(apiSave, ids) {
  await apiSave(ids);
  return ids;
}

async function toggleWatchlistOptimistically(state, marketId, apiSave) {
  const prev = [...state.watchlistIds];
  const next = toggleWatchlistId(prev, marketId);
  state.watchlistIds = next;
  try {
    await persistWatchlist(apiSave, next);
  } catch {
    state.watchlistIds = prev; // Rollback restores prior state on persistence failure.
    throw new Error("Failed to update watchlist");
  }
}
+Interviewer Debrief: What This Scenario Is Actually Testing
What the interviewer is testing:
Practical coding fluency, front-end fundamentals (hooks/transforms/sorting/state), and real-time pair-programming communication.
What strong candidates say:
They show strong JS/React fundamentals, explain trade-offs clearly, and distinguish “good enough for interview” from production-hardening steps.
What weak candidates miss:
They jump into code without clarifying assumptions, duplicate derived state, ignore stale/out-of-order updates, and skip accessibility or testing strategy.
Relevant React concepts:
useState for source state, useEffect for side effects/lifecycle cleanup, useMemo for expensive derived data only, immutable updates to ensure predictable re-renders.
Relevant product-engineering concepts:
Server as source-of-truth, optimistic UI reconciliation, idempotency, race-condition handling, monitoring, scalability boundaries, and user-trust-preserving failure UX.