diff --git a/examples/sdk/react/src/components/ButtonWithError.tsx b/examples/sdk/react/src/components/ButtonWithError.tsx
new file mode 100644
index 00000000..bdafa489
--- /dev/null
+++ b/examples/sdk/react/src/components/ButtonWithError.tsx
@@ -0,0 +1,20 @@
+import { useState } from 'react';
+
+export default function ButtonWithError() {
+ const [clicked, setClicked] = useState(false);
+
+ function throwOnClicked() {
+ if (clicked) {
+ throw new Error('Test throw in ButtonWithBoundary to demonstrate an Inner Error Boundary');
+ }
+ }
+
+ return (
+ <>
+ {throwOnClicked()}
+
+ >
+ );
+}
diff --git a/examples/sdk/react/src/Fallback.tsx b/examples/sdk/react/src/components/Fallback.tsx
similarity index 81%
rename from examples/sdk/react/src/Fallback.tsx
rename to examples/sdk/react/src/components/Fallback.tsx
index a7fe9fb3..103f82a3 100644
--- a/examples/sdk/react/src/Fallback.tsx
+++ b/examples/sdk/react/src/components/Fallback.tsx
@@ -1,6 +1,6 @@
-import './App.css';
+import '../App.css';
-export function Fallback() {
+export default function Fallback() {
return (
@@ -10,7 +10,8 @@ export function Fallback() {
alt="Sauce Labs"
/>
- This is the fallback component that gets rendered after a rendering error!
+ This is the fallback component that gets rendered after a rendering error within the main
+ ErrorBoundary!
Check your Backtrace console to see the Error and Component stacks!
diff --git a/examples/sdk/react/src/components/InnerFallback.tsx b/examples/sdk/react/src/components/InnerFallback.tsx
new file mode 100644
index 00000000..4c46abd7
--- /dev/null
+++ b/examples/sdk/react/src/components/InnerFallback.tsx
@@ -0,0 +1,9 @@
+import { useEffect } from 'react';
+import { toast } from 'react-toastify';
+
+export default function InnerFallback() {
+ useEffect(() => {
+ toast('Inner ErrorBoundary Triggered! Check your Backtrace console to see the Error and Component stacks.');
+ });
+ return null;
+}
diff --git a/examples/sdk/react/src/index.tsx b/examples/sdk/react/src/index.tsx
index fdcf8b84..f3724af1 100644
--- a/examples/sdk/react/src/index.tsx
+++ b/examples/sdk/react/src/index.tsx
@@ -2,7 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { ErrorBoundary, BacktraceClient } from '@backtrace/react';
-import { Fallback } from './Fallback';
+import Fallback from './components/Fallback';
import { SUBMISSION_URL } from './consts';
BacktraceClient.initialize({
@@ -21,7 +21,7 @@ BacktraceClient.initialize({
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
- }>
+ }>
,
diff --git a/package-lock.json b/package-lock.json
index d87c04f2..084d0146 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10431,9 +10431,10 @@
}
},
"node_modules/ts-loader": {
- "version": "9.4.3",
+ "version": "9.4.4",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.4.tgz",
+ "integrity": "sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==",
"dev": true,
- "license": "MIT",
"dependencies": {
"chalk": "^4.1.0",
"enhanced-resolve": "^5.0.0",
@@ -11230,8 +11231,9 @@
}
},
"node_modules/webpack": {
- "version": "5.87.0",
- "license": "MIT",
+ "version": "5.88.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
+ "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"dependencies": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
@@ -11770,8 +11772,9 @@
},
"node_modules/webpack-cli": {
"version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz",
+ "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==",
"dev": true,
- "license": "MIT",
"dependencies": {
"@discoveryjs/json-ext": "^0.5.0",
"@webpack-cli/configtest": "^2.1.1",
@@ -12272,10 +12275,13 @@
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"ts-jest": "^29.1.1",
- "typescript": "^5.0.4"
+ "ts-loader": "^9.4.4",
+ "typescript": "^5.0.4",
+ "webpack": "^5.88.2",
+ "webpack-cli": "^5.1.4"
},
"peerDependencies": {
- "react": ">=16.14.0"
+ "react": ">=16.8.0"
}
},
"packages/sdk-core": {
@@ -12845,7 +12851,10 @@
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"ts-jest": "^29.1.1",
- "typescript": "^5.0.4"
+ "ts-loader": "^9.4.4",
+ "typescript": "^5.0.4",
+ "webpack": "^5.88.2",
+ "webpack-cli": "^5.1.4"
}
},
"@backtrace/rollup-plugin": {
@@ -19357,7 +19366,9 @@
}
},
"ts-loader": {
- "version": "9.4.3",
+ "version": "9.4.4",
+ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.4.tgz",
+ "integrity": "sha512-MLukxDHBl8OJ5Dk3y69IsKVFRA/6MwzEqBgh+OXMPB/OD01KQuWPFd1WAQP8a5PeSCAxfnkhiuWqfmFJzJQt9w==",
"dev": true,
"requires": {
"chalk": "^4.1.0",
@@ -19881,7 +19892,9 @@
"dev": true
},
"webpack": {
- "version": "5.87.0",
+ "version": "5.88.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz",
+ "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==",
"requires": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^1.0.0",
@@ -20274,6 +20287,8 @@
},
"webpack-cli": {
"version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz",
+ "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==",
"dev": true,
"requires": {
"@discoveryjs/json-ext": "^0.5.0",
diff --git a/packages/react/package.json b/packages/react/package.json
index c4a3f42c..be402d5d 100644
--- a/packages/react/package.json
+++ b/packages/react/package.json
@@ -37,9 +37,12 @@
"jest": "^29.5.0",
"jest-environment-jsdom": "^29.5.0",
"ts-jest": "^29.1.1",
- "typescript": "^5.0.4"
+ "ts-loader": "^9.4.4",
+ "typescript": "^5.0.4",
+ "webpack": "^5.88.2",
+ "webpack-cli": "^5.1.4"
},
"peerDependencies": {
- "react": ">=16.14.0"
+ "react": ">=16.8.0"
}
}
diff --git a/packages/react/src/ErrorBoundary.tsx b/packages/react/src/ErrorBoundary.tsx
index 2348a6fc..0e6bfb14 100644
--- a/packages/react/src/ErrorBoundary.tsx
+++ b/packages/react/src/ErrorBoundary.tsx
@@ -7,6 +7,7 @@ type RenderFallback = () => ReactElement;
export interface Props {
children: ReactNode;
fallback?: ReactElement | RenderFallback;
+ name?: string;
}
export interface State {
@@ -32,7 +33,11 @@ export class ErrorBoundary extends Component
{
}
public async componentDidCatch(error: Error, info: ErrorInfo) {
- const report = new BacktraceReport(error);
+ const { name } = this.props;
+ const report = new BacktraceReport(error, {
+ 'errorboundary.name': name ?? 'main',
+ 'error.type': 'Unhandled exception',
+ });
report.addStackTrace(this.COMPONENT_THREAD_NAME, info.componentStack);
await this._client.send(report);
}