LogoLogo
HomePlatform IntegrationsDownloadsLogin
  • Welcome
  • 📌Introduction
    • Getting Started
      • Signing Up
      • Creating a Database
      • Platform Integrations
        • 💻Desktop
          • BugSplat Crash Reporting Library for Windows (Native C++)
            • Full Memory Dumps
            • Windows (Native C++) Dependencies
          • Windows (.NET Framework)
          • macOS
          • Linux
        • 🔀Cross-Platform
          • .NET Standard
          • Breakpad (Deprecated)
          • Crashpad
            • How to Build Google Crashpad
          • Deno
          • Electron
          • Java
          • Node.js
          • Python
          • Qt
        • 🎮Game Development
          • CRYENGINE
          • Nintendo Switch
          • PlayStation
          • Unreal Engine
            • Unreal Engine Plugin
          • Unity
          • Xbox
        • 📱Mobile
          • Android
          • Ionic
          • iOS
          • React Native
        • 🕸️Web
          • Angular
          • JavaScript
          • React
          • Vue
        • ⌛Downloads
      • Platform Samples
        • BugSplatTester (iOS)
        • BugSplatTester (macOS)
        • myConsoleCrasher (C++)
          • Address Sanitizer Reports
        • my-android-crasher
        • my-angular-crasher
        • my-electron-crasher
        • my-java-crasher
        • my-node-crasher
        • my-qt-crasher
        • my-react-crasher
        • my-unity-crasher
        • my-unreal-crasher
      • Inviting Team Members
      • Importing Crashes
      • Troubleshooting
      • Quickly Submitting Your First Crash in Under 5 Minutes
    • Development
      • Using the App
      • Symbol Files
        • Common Symbols
        • How to Manually Upload Symbols
        • Source Maps
        • Symbol Servers
        • Working with Symbol Files in Windows Environments
      • Searching
        • Table Filtering
        • Table Grouping
      • Grouping Crashes
      • Commenting
      • Integrations and Third Party Tools
        • Configurable Alerts
          • Slack
          • Microsoft Teams
          • Discord
          • Email
          • Webhook
        • Issue Trackers
          • Azure DevOps
          • Favro
          • Jira
          • GitHub Issues
          • GitLab
          • Monday.com
          • YouTrack
          • Auto-Creating Defects from BugSplat Databases in Attached Third-Party Issue Trackers
      • API
        • Web Application Endpoints
          • Charting
          • Company
          • Crash
          • Crashes
          • Crash Groups
          • Databases
          • Defect
          • Events
          • Import/Migrate
          • Support Response
          • User (GDPR)
          • Users
          • Versions
        • Crash Post Endpoints
        • OAuth2
        • Defect Tracker Options
        • Paging, Filtering, and Grouping
        • Platform Specific API's
          • C++ Native API
          • .NET API
    • Production
      • Versions
      • 🆕Regression Alerts
      • Security and Compliance
        • Security Program
        • BugSplat Security Program Inquirys
        • SOC 2
        • GDPR & UK GDPR Compliance
        • Avoid Collecting Personally Identifiable Information (PII)
        • Crash Expiry
        • Terms
        • Privacy Policy
      • Support Responses
      • BugSplat Status
  • 🍎Education
    • BugSplat Terminology
    • How-Tos
      • Creating Defects
      • Contacting End-Users
      • Crash Dialog Branding
      • Reprocess Crashes
      • Batch Reprocess Crashes
      • Using the Crash Attribute Feature
      • Send Feedback
      • Remove Crashes
    • Videos
      • BugSplat Product Walkthrough
    • FAQs
      • How Do I Upload Crashes with Python?
      • How Do I Remove Symbol Files?
      • Crash details 'Active Thread'
      • How long does it take to process a crash?
      • How BugSplat handles large crash volumes
      • How Does Crash Rate Limiting Work?
      • Add Custom Branding to Support Response
      • Finding Missing Reports
      • Using Dark Mode
      • What If My App or Game Grows Quickly?
      • Does BugSplat have an effect on application performance?
      • Manually Upload Crash Reports to BugSplat
      • How to configure proxy settings in BugSplat
      • Using BugSplat's public database
      • How to Upload Symbol Files with Symbol-Upload
      • Using SendPdbs to Automatically Upload Symbol Files
      • Managing Symbol Space
      • Why Group Crashes?
      • Uploading third-party DLLs without PDB files
      • Localized Support Responses for Windows C++, .NET, and macOS
      • BugSplat application uptime data
        • What are the upload size considerations with BugSplat accounts.
      • Is an application's source code safe when using BugSplat?
      • How to get correct callstacks with BugSplat in Steam
      • What is a crash reporter?
      • Common End-User Questions
        • Missing BugSplat.dll
        • What should I do if I get a BugSplat?
        • What is BsSndRpt.exe?
        • My software just crashed. Should I contact BugSplat for help?
  • 🏢Administration
    • Billing
      • Free Trial Overview
      • Plans and Billing Overview
      • How to Sign Up for a BugSplat Plan
      • Viewing Account Usage
      • Upgrading, Changing, or Canceling Your Plan
        • Upgrading or Downgrading Your Plan
        • Adding Additional Crashes and Storage Space
        • Updating Credit Card and Billing Information and Viewing Billing History
        • Updating Tax and VAT Information
        • Canceling Your Plan
      • Free and Discounted Plans
        • Free Plan Overview
        • Free Crash Reporting for Indie Game Development
        • Education
        • Open-Source
        • Good Causes
      • Plans, Upgrades, and Payments FAQ
        • Fair-Refund Policy
        • Update to Our Legacy Plans Guide
        • Updates to BugSplat Pricing Plans - March 2024
        • Using Coupons and Promotions at BugSplat
        • What is 'High Volume Fractional Crash Processing'?
    • Account
      • Migrating Databases
      • Deleting Databases
      • Deleting a Company Account
      • Changing Company Name
    • User Management
      • User Permissions
      • Deleting a User
      • Requesting Access
      • Login Page and Options
      • Password Settings and Reset Options
        • Required Password Reset - August 4th, 2023
      • Single Sign-On (SSO)
      • Multi-Factor Authentication (MFA)
      • Enforce MFA
      • Adding New Users in Companies with Multiple Databases
    • Contact us
  • 🐛About
    • What is BugSplat?
    • Why BugSplat?
    • Who is BugSplat?
      • Our Values
      • Charitable Giving
      • Brand Guidelines
    • Partnerships
    • Misc
      • Promotions
        • March 2024 - Game Developer Free Months of Service
      • Giveaways
        • April 8 - April 22, 2025
        • Feb 18 - March 17, 2025
        • Jan 15 - Feb 13, 2025
        • December 19-29, 2024
        • November 21–28, 2024
        • October 17-24th, 2024
        • September 19-26th, 2024
        • July 18 - July 23, 2024
        • April 18 - May 12, 2024
        • March 18 - April 03, 2024
        • November 15-30, 2023
        • October 9-23, 2023
  • 🔀Changelog
    • Changelog
Powered by GitBook
On this page
  • Overview
  • Get Started
  • Further Integration
  • Advanced Usage
  • The scope property
  • API
  • init()
  • getBugSplat()
  • ErrorBoundary
  • withErrorBoundary
  • useErrorHandler
  • Test Suite
  • Contributing

Was this helpful?

  1. Introduction
  2. Getting Started
  3. Platform Integrations
  4. Web

React

PreviousJavaScriptNextVue

Last updated 1 year ago

Was this helpful?

Overview

BugSplat supports the collection of errors in React applications. The npm package implements an component in order to capture rendering errors in child components and post them to BugSplat where they can be tracked and managed. Adding BugSplat to your React application is extremely easy.

Get Started

To start using BugSplat in your React application, run the following command at the root of your project. This will install @bugsplat/react and it's sub-dependency, .

npm i @bugsplat/react --save

In addition to standard package.json properties name and version, include a database property to your package.json file with the value of your BugSplat database. Make sure to replace {{YOUR_DATABASE_NAME}} with your actual database name.

// package.json
{
  "name": "my-app",
  "version": "1.2.0",
  "database": "{{YOUR_DATABASE_NAME}}"
  // ...
}

In the root of your project, import your project's package.json. Use it's name, database, and version properties to initialize the BugSplat client for sending crashes. This will instantiate a new client instance and store it internally.

// src/index.tsx

import { createRoot } from 'react-dom/client';
import { init } from '@bugsplat/react';
import App from './App';
import * as packageJson from '../package.json';

init({
  database: packageJson.database,
  name: packageJson.name,
  version: packageJson.version,
});

const root = createRoot(document.getElementById('root'));

root.render(<App />);

You can now wrap your component trees with ErrorBoundary to capture rendering errors and automatically post them to BugSplat with the internal client instance we initialized earlier.

// src/App.tsx

import { ErrorBoundary } from '@bugsplat/react';

export default function App() {
  return (
    <ErrorBoundary fallback={<h1>Oops, there was a problem.</h1>}>
      <Content>...</Content>
    </ErrorBoundary>
  );
}

You can also access the stored BugSplat instance anywhere by calling getBugSplat()

// src/App.tsx

import { getBugSplat } from '@bugsplat/react';

export default function App() {
  const handleClick = () => {
    getBugSplat().post('There was a problem');
  };

  return (
    <div>
      <h1>Hello, world!</h1>
      <button onClick={handleClick}>Post Error Report</button>
    </div>
  );
}

Further Integration

Want your error boundary to also handle errors that are not caught by ErrorBoundary, such as async errors or event handlers? No problem! useErrorHandler to the rescue. Pass your error to the callback returned from useErrorHandler in order to propagate the error to the nearest ErrorBoundary. You can also pass your error directly to useErrorHandler if you manage the error state yourself or get it from another library.

// src/App.tsx

import { useState } from 'react'
import { ErrorBoundary, useErrorHandler } from '@bugsplat/react';

function NestedComponent() {
  const handleError = useErrorHandler();

  const handleClick = async () => {
    try {
      await doThing();
    } catch (err) {
      handleError(err);
    }
  };

  return <button onClick={handleClick}>Do Thing</button>;
}

function NestedComponent2() {
  const [error, setError] = useState<Error>()

  useErrorHandler(error)

  const handleClick = async () => {
    try {
      await doThing()
    } catch (err) {
      setError(err)
    }
  }

  return <button onClick={handleClick}>Do Thing</button>;
}

export default function App() {
  return (
    <ErrorBoundary fallback={<h1>Oops, there was a problem.</h1>}>
      <NestedComponent />
      <NestedComponent2 />
    </ErrorBoundary>
  );
}

Providing an instance of BugSplat will allow ErrorBoundary to automatically post errors it catches to BugSplat.

The ErrorBoundary component is packed with props that can be used to customize it to fit your needs:

  • fallback

  • onMount

  • onUnmount

  • onError

  • beforePost

  • onReset

  • onResetKeysChange

  • disablePost

We strongly recommend passing a fallback prop that will be rendered when ErrorBoundary encounters an error.

The fallback prop can be any valid element:

function Component() {
  return (
    <ErrorBoundary fallback={<div>Oops, there was a problem.</div>}>
      ...
    </ErrorBoundary>
  );
}

...or a function that renders one

function Component() {
  return (
    <ErrorBoundary
      fallback={(fallbackProps) => <div>Oops, there was a problem.</div>}
    >
      ...
    </ErrorBoundary>
  );
}

If fallback is a function, it will be called with

  • error - the error caught be ErrorBoundary

  • componentStack - the component stack trace of the error

  • response - the BugSplat response of posting error to BugSplat, if applicable

  • resetErrorBoundary - a function to call in order to reset the ErrorBoundary state

The fallback will render any time the ErrorBoundary catches an error. It is useful to have a fallback UI to gracefully handle errors for your users, while still sending errors to BugSplat behind the scenes.

ErrorBoundary accepts a resetKeys prop that you can pass with an array of values that will cause it to automatically reset if one of those values changes. This gives you the power to control the error state from outside of the component.

function App() {
  const [error, setError] = useState<Error | null>();

  return (
    <ErrorBoundary
      fallback={(props) => <Fallback {...props} />}
      onReset={() => setError(null)}
      resetKeys={[error]}
    >
      {}
    </ErrorBoundary>
  );
}

Advanced Usage

The scope property

If you know what you're doing and want ErrorBoundary functionality beyond what is possible through props and callbacks, you can extend the BugSplat client and pass it to the ErrorBoundary through it's scope property.

import { BugSplat } from 'bugsplat';
import { ErrorBoundary } from '@bugsplat/react';
import SomeService from '@some/service';

class CustomBugSplatClient extends BugSplat {
  async post(error: CustomError) {
    await SomeService.post(error);

    return super.post(error);
  }
}

const client = new CustomBugSplatClient();

function App() {
  <ErrorBoundary scope={{ getClient: () => client }}>
    <ChildComponents />
  </ErrorBoundary>;
}

API

init()

interface BugSplatInit {
  /**
   * BugSplat database name that crashes should be posted to
   */
  database: string;
  /**
   * Name of application
   */
  application: string;
  /**
   * Version of application.
   */
  version: string;
}

/**
 * Initialize a new BugSplat instance and store the reference in scope
 *
 * @returns function with a callback argument that will be
 * called with the freshly initialized BugSplat instance
 *
 * - Useful to subscribe to events or set default properties
 */
export function init({
  database,
  application,
  version,
}: BugSplatInit): (initializer: (client: BugSplat) => void) => void;

/**
 * @example
 */
init({
  database: 'fred',
  application: 'my-react-crasher',
  version: '3.2.1',
})((bugSplat) => {
  bugSplat.setDefaultAppKey('Key!');
  bugSplat.setDefaultUser('User!');
  bugSplat.setDefaultEmail('fred@bedrock.com');
  bugSplat.setDefaultDescription('Description!');
});

getBugSplat()

/**
 * Get `BugSplat` instance from application scope
 */
const getBugSplat: () => BugSplat | null;

ErrorBoundary

interface FallbackProps {
  /**
   * Error that caused crash
   */
  error: Error;
  /**
   * Component stack trace leading to error
   */
  componentStack: string | null;
  /**
   * Crash post response
   */
  response: BugSplatResponse | null;
  /**
   * Reset error boundary state.
   *
   * This will pass any arguments to the end of onReset when it is called
   */
  resetErrorBoundary: (...args: unknown[]) => void;
}

type FallbackElement = ReactElement | null;

type FallbackRender = (props: FallbackProps) => FallbackElement;

/**
 * All props in ErrorBoundaryProps are optional,
 * but we recommend at least setting the fallback prop.
 */
interface ErrorBoundaryProps {
  /**
   * Callback called before error post to BugSplat.
   *
   * This will be awaited if it is a promise
   */
  beforePost: (
    bugSplat: BugSplat,
    error: Error | null,
    componentStack: string | null
  ) => void | Promise<void>;

  /**
   * Callback called when ErrorBoundary catches an error in componentDidCatch()
   *
   * This will be awaited if it is a promise
   */
  onError: (
    error: Error,
    componentStack: string,
    response: BugSplatResponse | null
  ) => void | Promise<void>;

  /**
   * Callback called on componentDidMount().
   */
  onMount: () => void;

  /**
   * Callback called on componentWillUnmount().
   */
  onUnmount: (state: ErrorBoundaryState) => void;

  /**
   * Callback called before ErrorBoundary resets internal state,
   * resulting in rendering children again. This should be
   * used to ensure that rerendering of children would not
   * repeat the same error that occurred.
   *
   * *This method is not called when ErrorBoundary is reset from a
   * change in resetKeys - use onResetKeysChange for that.*
   * @param state - Current error boundary state
   * @param ...args - Additional arguments passed from where it is called
   */
  onReset: (state: ErrorBoundaryState, ...args: unknown[]) => void;

  /**
   * Callback called when keys passed to resetKeys are changed.
   */
  onResetKeysChange: (prevResetKeys?: unknown[], resetKeys?: unknown[]) => void;

  /**
   * Array of values passed from parent scope. When ErrorBoundary
   * is in an error state, it will check each passed value
   * and automatically reset if any of the values have changed.
   */
  resetKeys?: unknown[];

  /**
   * Provide a fallback to render when ErrorBoundary catches an error.
   * Not required, but it is highly recommended to provide a value for this.
   *
   * This can be an element or a function that renders an element.
   */
  fallback?: FallbackElement | FallbackRender;

  /**
   * If true, caught errors will not be automatically posted to BugSplat.
   */
  disablePost?: boolean;

  /**
   * Child elements to be rendered when there is no error
   */
  children?: ReactNode | ReactNode[];

  /**
   * __Advanced Use__
   *
   * Object used by ErrorBoundary to retrieve a BugSplat client instance.
   *
   * Advanced users can extend the `BugSplat` class and use this property
   * to pass their own scope that will inject the client for use by
   * ErrorBoundary.
   */
  scope: { getClient(): BugSplat | null };
}

interface ErrorBoundaryState {
  error: Error | null;
  componentStack: string | null;
  response: BugSplatResponse | null;
}

/**
 * Handle errors that occur during rendering by wrapping
 * your component tree with ErrorBoundary. Any number of ErrorBoundary
 * components can be rendered in the tree and any rendering error will
 * propagate to the nearest one.
 */
class ErrorBoundary extends Component<
  ErrorBoundaryProps,
  ErrorBoundaryState
>

withErrorBoundary

/**
 * Higher order component to wrap your component tree with ErrorBoundary
 */
function withErrorBoundary<P extends Record<string, unknown>>(
  Component: ComponentType<P>,
  errorBoundaryProps: ErrorBoundaryProps = {}
): ComponentType<P>;

useErrorHandler

/**
 * Utility hook to declaratively or imperatively propagate an
 * error to the nearest error boundary.
 *
 * *Should be called from a child of ErrorBoundary*
 *
 * Propagate error:
 *
 * * Declaratively - by passing an error prop
 * * Imperatively - by calling the returned handler with an error
 *
 * @param errorProp - Will throw when a truthy value is passed
 * @returns Error handler that will throw when called with a truthy value
 */
function useErrorHandler(errorProp?: unknown): (error: unknown) => void;

Test Suite

This package contains both unit and integration tests. To run them, use the package.json scripts provided.

Tests
Command

Unit

npm run test

Integration

npm run test:integration

Contributing

This package re-exports all exports from .

BugSplat ❤️s open source! If you feel that this integration can be improved, please open an . If you have an awesome new feature you'd like to implement, we'd love to merge your . You can also reach out to us via an email to or the in-app chat on bugsplat.com.

📌
🕸️
@bugsplat/react
ErrorBoundary
bugsplat
bugsplat-js
Issue
Pull Request
support@bugsplat.com