Files
2026-07-12 10:17:17 -04:00

2.2 KiB

React Runtime Crash Patterns

Invalid Date → RangeError (white screen)

new Date(undefined) or new Date(null) creates an Invalid Date. Calling .toLocaleDateString() or Intl.DateTimeFormat.format() on it throws RangeError: Invalid time value — an uncaught runtime error that blanks the page.

Fix: Guard all date formatting functions:

function formatDate(iso: string | undefined | null) {
  if (!iso) return '—';
  return new Intl.DateTimeFormat('en-US', { ... }).format(new Date(iso));
}

Detection: grep for new Date( calls in page components and verify each has a null/undefined guard.

Nested component re-mount (input focus loss)

Defining a child component as a nested function inside a parent causes React to destroy/recreate it on every parent render. If the parent re-renders from a state update (e.g., zustand store change while typing), the input loses focus on every keystroke.

Symptom: Each character typed dismisses focus; user must click back into the field for the next character.

Fix: Extract to a file-level memo component:

const ServiceRow = memo(function ServiceRow({ service, onUpdate, ... }: Props) {
  return <input value={service.price} onChange={e => onUpdate({ price: parseFloat(e.target.value) })} />
});

Anti-pattern (causes focus loss):

function Parent() {
  const Child = ({ item }) => <input ... />;  // New identity every render
  return items.map(i => <Child key={i.id} item={i} />);
}

Blank screen with empty console

When a React lazy-loaded chunk has an import error, the page shows blank with zero console errors. The error is swallowed by the Suspense boundary. Fix: temporarily switch to eager imports in App.tsx to surface the error, then revert to lazy once fixed.

tsc clean ≠ runtime clean

TypeScript compilation success does not catch:

  • JSON.parse on potentially-malformed strings
  • new Date(undefined) → RangeError
  • .reduce() / .map() on non-array values
  • Missing context providers (useToast without ToastProvider)

These all surface as blank pages or runtime crashes. After parallel fan-outs, smoke-test each page by navigating to its URL.