Skip to content

React SDK

@errpulse/react captures frontend errors, failed network requests, and React component crashes from your React application.

Installation

bash
npm install @errpulse/react

ErrPulseProvider

Wrap your app with the provider to start capturing errors:

tsx
import { ErrPulseProvider } from "@errpulse/react";

function App() {
  return (
    <ErrPulseProvider endpoint="http://localhost:3800">
      <YourApp />
    </ErrPulseProvider>
  );
}

Props Reference

PropTypeDefaultDescription
endpointstringrequiredErrPulse server URL
projectIdstringundefinedProject identifier for multi-project setups
captureConsoleErrorsbooleantrueCapture console.error calls
captureConsoleLogsbooleanfalseCapture console.log/warn/info/debug to Logs
captureFetchbooleantrueIntercept and track fetch requests
captureXHRbooleantrueIntercept and track XMLHttpRequest calls
captureResourceErrorsbooleantrueCapture failed img/script/css loads
errorBoundaryFallbackReactNode | (error: Error) => ReactNodeundefinedFallback UI for React crashes

Full Example

tsx
<ErrPulseProvider
  endpoint="http://localhost:3800"
  projectId="my-web-app"
  captureConsoleErrors={true}
  captureConsoleLogs={false}
  captureFetch={true}
  captureXHR={true}
  captureResourceErrors={true}
  errorBoundaryFallback={(error) => (
    <div>
      <h2>Something went wrong</h2>
      <p>{error.message}</p>
    </div>
  )}
>
  <App />
</ErrPulseProvider>

useErrPulse Hook

Use the useErrPulse hook for manual error and message capture:

tsx
import { useErrPulse } from "@errpulse/react";

function CheckoutButton() {
  const { captureError, captureMessage } = useErrPulse();

  const handleClick = async () => {
    try {
      await processPayment();
      captureMessage("Payment successful", "info", { plan: "pro" });
    } catch (err) {
      captureError(err, { step: "payment" });
    }
  };

  return <button onClick={handleClick}>Checkout</button>;
}

captureError(error, extra?)

ts
captureError(new Error("Form validation failed"), { field: "email" });
captureError("Something went wrong"); // String also accepted

captureMessage(message, severity?, extra?)

ts
captureMessage("User clicked CTA", "info");
captureMessage("API response slow", "warning", { duration: 5200 });
captureMessage("Upload failed", "error", { fileSize: "50MB" });

Error Boundary

The ErrPulseProvider includes a built-in error boundary. When a React component crashes, it:

  1. Captures the error with full stack trace and component stack
  2. Reports it to the ErrPulse server
  3. Renders the errorBoundaryFallback if provided, or nothing

You can also use the error boundary component directly:

tsx
import { ErrPulseErrorBoundary } from "@errpulse/react";

function App() {
  return (
    <ErrPulseErrorBoundary fallback={<p>Something broke</p>}>
      <RiskyComponent />
    </ErrPulseErrorBoundary>
  );
}

What Gets Captured

The SDK installs the following instruments automatically:

InstrumentWhat It CapturesHow
Global error handlerJavaScript runtime errorswindow.onerror
Rejection handlerUnhandled promise rejectionswindow.onunhandledrejection
Fetch interceptorFailed/errored fetch requestsMonkey-patches window.fetch
XHR interceptorFailed/errored XHR requestsMonkey-patches XMLHttpRequest
Console interceptorconsole.error callsWraps console.error
Console log interceptorconsole.log/warn/info/debugWraps console methods (opt-in)
Resource error handlerFailed img/script/css loadsCapture-phase event listener
Error boundaryReact component crashesReact error boundary

Request Detail Capture

The fetch interceptor automatically captures request and response details for every outgoing fetch call:

  • Request headers — sanitized (sensitive headers like authorization and cookie are redacted)
  • Response headers — captured from the response
  • Request body — captured for string and URLSearchParams bodies (Blob/ArrayBuffer/FormData are skipped for performance)
  • Response body — captured by cloning the response stream (does not consume the original)

Performance

Request and response bodies are capped at 16 KB each. Anything larger is truncated with a ...[truncated] indicator. Response bodies are read via response.clone() so the original stream remains available to your application code.

Correlation ID

The React SDK automatically injects an X-ErrPulse-Correlation-ID header into every outgoing fetch request. This links frontend requests to backend errors:

Frontend: fetch("/api/checkout")
  → Header: X-ErrPulse-Correlation-ID: a1b2c3d4e5f6

Backend: expressRequestHandler() reads the header
  → If an error occurs, both the request and error share the same correlation ID

Dashboard: Shows the full chain from user action → request → error

This happens automatically when both @errpulse/node and @errpulse/react are installed. No configuration required.

Page Unload

The SDK uses navigator.sendBeacon() on page unload to flush any remaining buffered events. This ensures errors captured right before the user navigates away are still delivered to the server.

DevTools Widget

<ErrPulseDevTools /> is a floating in-app debug panel that lets you see errors, console logs, and network requests without leaving your app or opening browser DevTools.

tsx
import { ErrPulseProvider, ErrPulseDevTools } from "@errpulse/react";

function App() {
  return (
    <ErrPulseProvider endpoint="http://localhost:3800" projectId="my-app">
      <YourApp />
      <ErrPulseDevTools />
    </ErrPulseProvider>
  );
}

Props

PropTypeDefaultDescription
position"bottom-right" | "bottom-left" | "top-right" | "top-left""bottom-right"Initial corner position
initialOpenbooleanfalseStart with panel open
enabledbooleanundefinedForce on/off. Default: visible in development, hidden in production

Features

  • Errors tab — every captured error with severity, type, timestamp. Click to expand for full stack trace, page URL, request details, and server-provided plain-English explanations
  • Console tab — live console.log, .warn, .info, .debug output. Logs containing objects show a collapsed preview — click to expand a syntax-highlighted JSON tree viewer
  • Network tab — all HTTP requests with method, URL, status, duration. Click to expand for full request/response headers, request body, and response payload as formatted JSON
  • Expandable panel — click the expand button to go near-fullscreen for reading large payloads and stack traces
  • Draggable — grab the floating icon and drag it anywhere on screen. Position persists across page reloads via localStorage
  • Keyboard shortcutCtrl+Shift+E toggles the panel
  • Shadow DOM — fully isolated styles, no CSS leakage to or from your app
  • Dev-only by default — automatically hidden in production unless enabled={true}

Hybrid Architecture

The DevTools widget uses a hybrid data approach:

  • Local capture — errors, logs, and network requests appear instantly, even without the ErrPulse server. The widget subscribes to the SDK's internal event stream.
  • Server enrichment — when the server is running, the widget fetches grouped error data with occurrence counts and plain-English explanations via REST API, and subscribes to real-time updates via WebSocket.

The footer shows connection status: green dot when connected to the server, orange dot when running in local-only mode.

TIP

The DevTools widget works great alongside the full dashboard. Use the widget for quick in-app debugging, and the dashboard for deeper analysis, trends, and multi-project monitoring.

Released under the MIT License.