Skip to content

Commit 2e013bf

Browse files
author
Sébastien Henau
committed
add flare react error handler function for react 19 support
1 parent 9a187fa commit 2e013bf

File tree

6 files changed

+54
-2
lines changed

6 files changed

+54
-2
lines changed

packages/react/src/FlareErrorBoundary.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { flare } from '@flareapp/js';
22
import { Component, ErrorInfo, type PropsWithChildren, type ReactNode } from 'react';
33

44
import { formatComponentStack } from './format-component-stack';
5+
import { FlareReactContext } from './types';
56

67
export type FlareErrorBoundaryFallbackProps = {
78
error: Error;
@@ -35,7 +36,7 @@ export class FlareErrorBoundary extends Component<FlareErrorBoundaryProps, Flare
3536
errorInfo,
3637
});
3738

38-
const context = {
39+
const context: FlareReactContext = {
3940
react: {
4041
componentStack: formatComponentStack(errorInfo.componentStack ?? ''),
4142
},
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
export function convertToError(error: unknown): Error {
2+
if (error instanceof Error) {
3+
return error;
4+
}
5+
if (typeof error === 'string') {
6+
return new Error(error);
7+
}
8+
9+
return new Error(String(error));
10+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { flare } from '@flareapp/js';
2+
3+
import { convertToError } from './convert-to-error';
4+
import { formatComponentStack } from './format-component-stack';
5+
import { FlareReactContext } from './types';
6+
7+
export type FlareReactErrorHandlerCallback = (error: unknown, errorInfo: { componentStack?: string }) => void;
8+
9+
export function flareReactErrorHandler(callback?: FlareReactErrorHandlerCallback): FlareReactErrorHandlerCallback {
10+
return (error: unknown, errorInfo: { componentStack?: string }) => {
11+
const errorObject = convertToError(error);
12+
13+
const context: FlareReactContext = {
14+
react: {
15+
componentStack: formatComponentStack(errorInfo.componentStack ?? ''),
16+
},
17+
};
18+
19+
flare.report(errorObject, context);
20+
21+
callback?.(error, errorInfo);
22+
};
23+
}

packages/react/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ export {
44
type FlareErrorBoundaryFallbackProps,
55
type FlareErrorBoundaryState,
66
} from './FlareErrorBoundary';
7+
8+
export { flareReactErrorHandler, type FlareReactErrorHandlerCallback } from './flare-react-error-handler';

packages/react/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export type FlareReactContext = {
2+
react: {
3+
componentStack: string[];
4+
};
5+
};

playground/react/main.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,15 @@ import { App } from './App';
66

77
createSidebar();
88

9-
createRoot(document.querySelector('#root')!).render(<App />);
9+
createRoot(document.querySelector('#root')!, {
10+
// Not using callbacks here because FlareErrorBoundary already reports caught errors. Using both would result in duplicate reports.
11+
// onCaughtError: flareReactErrorHandler((error, errorInfo) => {
12+
// console.log('onCaughtError', error, errorInfo.componentStack);
13+
// }),
14+
// onUncaughtError: flareReactErrorHandler((error, errorInfo) => {
15+
// console.log('onUncaughtError', error, errorInfo.componentStack);
16+
// }),
17+
// onRecoverableError: flareReactErrorHandler((error, errorInfo) => {
18+
// console.log('onRecoverableError', error, errorInfo.componentStack);
19+
// }),
20+
}).render(<App />);

0 commit comments

Comments
 (0)