Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
## 1.7.0

This release adds a new `RaygunErrorBoundary` React component for capturing render-time errors with the React `componentStack`, upgrades the underlying native SDKs (`raygun4android` 5.2.1, `raygun4apple` 2.1.6), modernises the Android build for Gradle 9 / AGP 8.x (`compileSdkVersion 36`), and refreshes the demo projects to React Native 0.84.

- feat: Add `RaygunErrorBoundary` component for capturing React render-time errors with `componentStack` (#228)
- feat: bump raygun4apple to 2.1.6 (#226) (2026-03-12)
- feat: bump to raygun4android v5.2.1 (#224) (2026-03-03)
- fix: breaking changes in raygun4android 5.2.1 (#225) (2026-03-03)
- fix: use compileSdkVersion 36 (#223) (2026-03-03)
- fix: unhandled exception tag and fatal tag overwrite in CrashReporter (#217) (2026-02-10)
- chore: upgrade demo projects and align dependencies (#227) (2026-03-19)
- chore(deps): bump react-native from 0.83.1 to 0.84.1 in /demo (#220) (2026-03-02)
- chore(deps): bump react-native from 0.80.1 to 0.83.1 in /demo (#209) (2026-01-06)
- chore(deps): bump @react-navigation/native from 7.1.31 to 7.2.2 in /demo (#232) (2026-04-01)
- chore(deps): bump @react-navigation/bottom-tabs in /demo (#219, #207, #203, #196, #189, #181) (2025-08 → 2026-03)
- chore(deps): bump react-native-screens (#205, #193) (2025-11 → 2026-01)
- chore(deps): bump react and @types/react in /demo (#201, #183, plus 2026-02-02) (2025-08 → 2026-02)
- chore(deps-dev): bump @react-native-community/cli-platform-android (#229, #195) (2025-11, 2026-04)
- chore(deps-dev): bump @react-native-community/cli-platform-ios in /demo (#230, #211) (2026-02, 2026-04)
- chore(deps-dev): bump @react-native-community/cli (#188, plus 2026-02-02) (2025-10 → 2026-02)
- chore(deps-dev): bump @react-native/babel-preset in /demo (#221, #182) (2025-08, 2026-03)
- chore(deps-dev): bump @react-native/metro-config in /demo (#218, #202) (2025-12, 2026-03)
- chore(deps-dev): bump @react-native/eslint-config in /demo (#222, #185) (2025-10, 2026-03)
- chore(deps-dev): bump @react-native/typescript-config in /demo (#204) (2025-12-10)
- chore(deps-dev): bump eslint from 8.57.1 to 9.39.2 in /demo (#208) (2026-01-02)
- chore(deps-dev): bump typescript (#180, plus 2026-02-02) (2025-08 → 2026-02)
- chore(deps-dev): bump prettier (#184, #206, plus 2026-02-02) (2025-08 → 2026-02)
- chore(deps-dev): bump @babel/core from 7.28.5 to 7.29.0 in /demo (#233) (2026-04-01)
- chore(deps-dev): bump @babel/preset-env from 7.28.0 to 7.28.5 in /demo (#194) (2025-11-01)
- chore(deps-dev): bump @babel/runtime from 7.27.6 to 7.28.4 in /demo (#187) (2025-10-01)
- chore(deps): bump on-headers and compression in /demo and /ExpoDemo (#178, #179) (2025-07-22)
- chore(deps): bump gradle/actions from 4 to 6 (#199, #234) (2025-11, 2026-04)
- chore(deps): bump actions/checkout from 4 to 6 (#191, #200) (2025-10, 2025-12)
- chore(deps): bump actions/setup-node from 4 to 6 (#190, #198) (2025-10, 2025-11)
- chore(deps): bump actions/setup-java from 4 to 5 (#192) (2025-10-01)

## 1.6.0

This release fixes compatibility issues with the recent React-Native versions 0.79+, and it is backwards compatible with older versions as well.
Expand Down
58 changes: 47 additions & 11 deletions ExpoDemo/app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,63 @@
import { useState } from "react";
import { Button, Text, View } from "react-native";
import RaygunClient, { LogLevel, RaygunClientOptions } from "raygun4reactnative";
import RaygunClient, {
LogLevel,
RaygunClientOptions,
RaygunErrorBoundary,
} from "raygun4reactnative";

export default function Index() {
const options: RaygunClientOptions = {
apiKey: "INSERT_YOUR_API_KEY_HERE",
version: "0.1.2",
enableCrashReporting: true,
logLevel: LogLevel.verbose,
};

RaygunClient.init(options);

Comment thread
velocitysystems marked this conversation as resolved.
function Crasher() {
const [shouldCrash, setShouldCrash] = useState(false);

const options: RaygunClientOptions = {
apiKey: "INSERT_YOUR_API_KEY_HERE",
version: "0.1.2",
enableCrashReporting: true,
logLevel: LogLevel.verbose,
};

RaygunClient.init(options);
if (shouldCrash) {
throw new Error("Render-time error from Expo demo");
}

return (
<Button
title="Trigger render error"
onPress={() => setShouldCrash(true)}
/>
);
}

export default function Index() {
return (
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
gap: 16,
}}
>
<Text>Raygun Demo</Text>
<Button title="Send Error" onPress={() => RaygunClient.sendError(Error("Error from Expo app"))} />
<Button
title="Send Error"
onPress={() => RaygunClient.sendError(Error("Error from Expo app"))}
/>

<RaygunErrorBoundary
tags={["demo:expo"]}
fallback={({ error, reset }) => (
<View style={{ alignItems: "center", gap: 8 }}>
<Text>Caught by RaygunErrorBoundary:</Text>
<Text>{error.message}</Text>
<Button title="Reset" onPress={reset} />
</View>
)}
>
<Crasher />
</RaygunErrorBoundary>
</View>
);
}
8 changes: 8 additions & 0 deletions demo/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Home from "./screens/Home";
import CrashReporting from "./screens/CrashReporting";
import RealUserMonitoring from "./screens/RealUserMonitoring";
import ErrorBoundaryScreen from "./screens/ErrorBoundary";
import {raygunClient} from "./utils/Utils";
import {LogLevel, RaygunClientOptions} from "raygun4reactnative";

Expand Down Expand Up @@ -48,6 +49,13 @@ function Tabs() {
tabBarLabel: 'RUM'
}}
/>
<Tab.Screen
name="ErrorBoundary"
component={ErrorBoundaryScreen}
options={{
tabBarLabel: 'Boundary'
}}
/>
</Tab.Navigator>
);
}
Expand Down
8 changes: 4 additions & 4 deletions demo/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"@react-native-community/checkbox": "^0.5.20",
"@react-navigation/bottom-tabs": "^7.15.2",
"@react-navigation/native": "^7.2.2",
"raygun4reactnative": "file:raygun4reactnative-1.6.0.tgz",
"raygun4reactnative": "file:raygun4reactnative-1.7.0.tgz",
"react": "19.2.3",
"react-native": "^0.84.1",
"react-native-safe-area-context": "^5.4.1",
Expand Down
59 changes: 59 additions & 0 deletions demo/screens/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, {useState} from "react";
import {Button, SafeAreaView, ScrollView, Text, View} from "react-native";
import {RaygunErrorBoundary} from "raygun4reactnative";
import {styles} from "../utils/Utils";

function Crasher() {
const [shouldCrash, setShouldCrash] = useState(false);

if (shouldCrash) {
throw new Error("Test Error: render-time error from ErrorBoundary demo");
}

return (
<Button
title={"Trigger render error"}
color={"red"}
onPress={() => setShouldCrash(true)}
/>
);
}

export default function ErrorBoundaryScreen() {
return (
<SafeAreaView>
<ScrollView style={styles.scrollView}>
<View style={styles.mainView}>
<View style={styles.secondView}>
<Text style={styles.title}>RaygunErrorBoundary</Text>
<Text style={styles.subtitle}>
Render-time errors thrown inside the boundary are reported to
Raygun (with React `componentStack` as custom data) and the
fallback UI is shown until reset.
</Text>
</View>

<View style={styles.secondView}>
<RaygunErrorBoundary
tags={["demo:error-boundary"]}
customData={{screen: "ErrorBoundary"}}
onError={(error) => {
console.log("[ErrorBoundary] caught:", error.message);
}}
fallback={({error, reset}) => (
<View style={{alignItems: "center"}}>
<Text style={styles.subtitle}>
Caught: {error.message}
</Text>
<Button title={"Reset"} color={"green"} onPress={reset} />
</View>
)}
>
<Crasher />
</RaygunErrorBoundary>
</View>
</View>
</ScrollView>
</SafeAreaView>
);
}
57 changes: 57 additions & 0 deletions sdk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
- [sendError](#senderrorerror-error-details-manualcrashreportdetails)
- [setMaxReportsStoredOnDevice](#setmaxreportsstoredondevicesize-number)
- [sendRUMTimingEvent](#sendrumtimingeventeventtype-realusermonitoringtimings-name-string-timeusedinms-number)
- [Components](#components)
- [RaygunErrorBoundary](#raygunerrorboundary)
- [Raygun specific types](#raygun-specific-types)
- [BeforeSendHandler](#beforesendhandler)
- [GroupingKeyHandler](#groupingkeyhandler)
Expand Down Expand Up @@ -468,6 +470,8 @@ can utilize this method, and send the error through to Raygun. Appended to this
ManualCrashReportDetails object. This non-mandatory object can apply specific tags and CustomData to
the error you are sending away as well as the global tags and CustomData.

For React render-time errors, see [RaygunErrorBoundary](#raygunerrorboundary).

See also:<br/>
[CustomData](#customdata)
<br/>
Expand Down Expand Up @@ -582,6 +586,59 @@ RaygunClient.sendRUMTimingEvent(RealUserMonitoringTimings.ViewLoaded, 'name of t
RaygunClient.sendRUMTimingEvent(RealUserMonitoringTimings.NetworkCall, 'name of the network event', 255);
```

<br/>

## Components

### RaygunErrorBoundary

`RaygunErrorBoundary` is a React [error boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) component that catches render-time errors anywhere in its child tree, reports them to Raygun (with the React `componentStack` attached as custom data), and renders a fallback UI in place of the crashed subtree.

Use this for render-time errors. For errors caught manually in event handlers or async code, continue to use [sendError](#senderrorerror-error-details-manualcrashreportdetails).

The boundary does **not** catch errors thrown by the `fallback` itself, errors in event handlers, or errors thrown asynchronously. For those, use `try/catch` with `RaygunClient.sendError`, and nest another `RaygunErrorBoundary` above if your `fallback` can throw.

#### Props

| Prop | Type | Description |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `children` | `ReactNode` | The subtree to protect. |
| `fallback?` | `ReactNode \| ({ error, componentStack, reset }) => ReactNode` | UI to render after an error. As a function, receives the captured error, the React `componentStack`, and a `reset` callback that clears the error and remounts `children`. If omitted, the boundary renders `null` after an error (report-only mode). On the very first fallback render, `componentStack` may be an empty string before being populated on the immediately-following re-render. The function must not throw. |
| `tags?` | `string[]` | Tags to attach to the report. Always merged (de-duplicated) with `'error-boundary'`. |
| `customData?` | `CustomData` | Custom data to attach to the report. The captured `componentStack` is always merged in under the `componentStack` key and overrides any user-supplied value with the same key. |
| `onError?` | `(error: Error, info: ErrorInfo) => void` | Called after the error is captured. |
| `onReset?` | `(error: Error \| null, info: ErrorInfo \| null) => void` | Called when `reset` is invoked from the fallback. |

#### Basic example

```tsx
import { RaygunErrorBoundary } from 'raygun4reactnative';

<RaygunErrorBoundary fallback={<MyErrorScreen />}>
<App />
</RaygunErrorBoundary>
```

#### Render-prop fallback with reset

```tsx
import { RaygunErrorBoundary } from 'raygun4reactnative';

<RaygunErrorBoundary
tags={['feature:checkout']}
fallback={({ error, reset }) => (
<View>
<Text>Something went wrong: {error.message}</Text>
<Button title="Try again" onPress={reset} />
</View>
)}
>
<CheckoutScreen />
</RaygunErrorBoundary>
```

See also: [CustomData](#customdata), [sendError](#senderrorerror-error-details-manualcrashreportdetails).

---

## Raygun specific types
Expand Down
Loading
Loading