Bug tracking for React — session replay, console + HAR (2026)
4 min read · JavaScript
What React teams ship with BugMojo
React is the most-shipped frontend framework in the world, and it has the most distinctive failure modes in the world. The bugs your team will spend the most time on are not "the button doesn't render" — they're hydration mismatches, race conditions inside useEffect, stale closures around setState, suspense boundary thrashing, and concurrent-mode re-entry. Each of these is invisible in a screenshot and obvious in a session replay.
A bug report from a React app needs three things a screenshot cannot provide: the DOM state at the failure instant (because hydration bugs differ between server and client trees), the console warnings React emitted (because React 19 added several DEV-only signals that point at the root cause), and the network requests that fed the bad state (because almost every "it works on my machine" React bug traces back to data shape). BugMojo captures all three by default.
This guide is for QA engineers, PMs, and developers shipping React apps in 2026 — what to capture, how to triage, and how to wire bug reports straight into a Linear/Jira/GitHub issue with one click.
React gotchas
Framework-specific failure modes our team has shipped through. Each one is hard to spot in a screenshot — easy to spot in a session replay.
Hydration mismatches look like rendering bugs
High impactWhen the server renders different HTML than the client expects, React 19 patches the DOM but logs a warning and downgrades performance. The visible bug (text disappearing, layout shifting) is downstream of the real issue: server/client state divergence. Capture the console — the warning names the exact mismatched node.
useEffect cleanup runs in StrictMode twice
Medium impactIn dev mode, React intentionally invokes effects twice to catch missing cleanup. Bugs that "only happen in dev" almost always have a missing return statement in useEffect. The visible symptom is doubled API requests; the actual fix is in the cleanup function.
Suspense boundaries swallow async errors
High impactA throw inside a component wrapped in Suspense triggers the fallback, not your error boundary, unless you wrap it explicitly. Bug reports that say "the loading spinner never goes away" are almost always an unthrown rejection inside a Suspense subtree.
State updates from unmounted components
Medium impactReact no longer warns about setState-on-unmounted (that warning was removed in 18) but the underlying problem still causes memory leaks and ghost UI. Capture the replay PLUS the network log — the rogue setState usually fires from a stale fetch response.
Server Components mixed with Client Components
Medium impactA `"use client"` directive at the top of a file is silently inherited by every export from that file. Bug: a small client component accidentally pulls a huge tree into the client bundle. Bug report needs the network HAR to show the bundle size diff.
Common React bugs
Real bug patterns from React apps, with the symptom you’ll see in a bug report and the fix that actually works.
Infinite re-render loop from object dependency
- Symptom
- Component re-renders forever. React eventually crashes with "Maximum update depth exceeded." Page becomes unresponsive.
- Fix
- A useEffect dep array contains an object/array recreated each render. Wrap it in useMemo, or depend on its stable fields. Replay shows the render count climbing in DevTools.
// ❌ bug — new object each render
useEffect(() => { load(filters); }, [filters]);
// ✅ fix — stable identity
const filterKey = JSON.stringify(filters);
useEffect(() => { load(filters); }, [filterKey]);Stale closure inside event handler
- Symptom
- A button click uses an old value. State looks correct in DevTools but the handler reads yesterday's data.
- Fix
- The handler captured state at mount time. Move the read inside the handler, or use useRef for values that must always be current. Replay + console snapshot makes this obvious — the value the user saw vs the value the handler sent diverge.
// ❌ stale capture
const handler = () => fetch('/api', { body: count });
// ✅ ref always current
const countRef = useRef(count);
useEffect(() => { countRef.current = count; });
const handler = () => fetch('/api', { body: countRef.current });Hydration mismatch from Date.now() / Math.random()
- Symptom
- Console warning: "Hydration failed because the initial UI does not match what was rendered on the server." Text flickers on first paint.
- Fix
- Anything non-deterministic (timestamps, random ids, locale-dependent formatting) must be deferred until after hydration. Use useEffect to set the value, OR wrap in `suppressHydrationWarning` and accept the mismatch on that one node.
// ❌ mismatch
return <span>{Date.now()}</span>;
// ✅ defer
const [time, setTime] = useState<number | null>(null);
useEffect(() => setTime(Date.now()), []);Form re-renders the entire tree on every keystroke
- Symptom
- Typing in one input causes the whole page to feel sluggish. DevTools Profiler shows hundreds of components re-rendering per keystroke.
- Fix
- A controlled input lives at the wrong level of the tree, or context is over-broad. Move state down (useState in the input itself, lift only on submit), or split context.
Setup
There is no SDK — BugMojo is a Chrome extension. It works on any React build (CRA, Vite, Next.js, Remix). For source-mapped console errors, point BugMojo at your source maps in Settings → Source Maps.
# 1. Install BugMojo from the Chrome Web Store
# 2. Open your React app
# 3. Highlight the broken element → click "Capture"
# 4. BugMojo attaches DOM replay, console, network HAR, build infoBugMojo vs alternatives
The honest comparison — where BugMojo wins, and where another tool might serve you better.
| Capability | BugMojo | Plain screenshot / Jira |
|---|---|---|
| DOM session replay | ✅ rrweb-based | ❌ |
| Console errors auto-captured | ✅ | ❌ |
| Network HAR auto-captured | ✅ with PII redaction | ❌ |
| React DevTools state snapshot | ✅ | ❌ |
| Time-to-file a bug report | ~15 seconds | 2–5 minutes |
| One-click sync to Jira/Linear/GitHub | ✅ | manual copy-paste |
Frequently asked questions
Sources
- React docs — Hydration mismatch warning — react.dev (2025)
- rrweb open-source session replay — rrweb-io (2025)

