Error boundary
The FlareErrorBoundary component catches errors during rendering, in lifecycle methods, and in constructors of the component tree below it. When an error is caught, it is automatically reported to Flare with React-specific context including a structured component stack trace.
Basic usage
Wrap your component tree (or parts of it) in the FlareErrorBoundary:
import { FlareErrorBoundary } from '@flareapp/react';
function App() {
return (
<FlareErrorBoundary>
<MyComponent />
</FlareErrorBoundary>
);
}
Displaying a fallback UI
Without a fallback prop, the error boundary renders nothing when an error is caught. The fallback prop accepts either a static ReactNode or a render function:
// Static fallback
<FlareErrorBoundary fallback={<p>Something went wrong.</p>}>
<App />
</FlareErrorBoundary>
The render function receives the caught error, the parsed componentStack (as a string array), and a resetErrorBoundary function to clear the error state:
// Render function fallback with error details and reset
<FlareErrorBoundary
fallback={({ error, componentStack, resetErrorBoundary }) => (
<div>
<h2>Something went wrong</h2>
<p>{error.message}</p>
<pre>{componentStack.join('\n')}</pre>
<button onClick={resetErrorBoundary}>Try again</button>
</div>
)}
>
<App />
</FlareErrorBoundary>
Resetting the error boundary
You can automatically reset the error boundary when certain values change using the resetKeys prop. When any value in the array changes between renders (compared per-index via Object.is), or when the array's length changes, the boundary automatically resets and re-renders its children.
A common use case is resetting the boundary when the user navigates to a different page:
function App() {
const location = useLocation();
return (
<FlareErrorBoundary
resetKeys={[location.pathname]}
onReset={(error) => {
console.log('Navigated away from error, previous error:', error?.message);
}}
fallback={<p>Something went wrong.</p>}
>
<Routes />
</FlareErrorBoundary>
);
}
The onReset callback fires when the error boundary resets (either via resetErrorBoundary() from the fallback or via resetKeys changing). It receives the previous error, allowing conditional cleanup:
// Example using React Query (TanStack Query) to refetch stale data on reset
const queryClient = useQueryClient();
<FlareErrorBoundary
onReset={(error) => {
console.log('Recovering from:', error?.message);
queryClient.invalidateQueries();
}}
fallback={({ resetErrorBoundary }) => (
<button onClick={resetErrorBoundary}>Retry</button>
)}
>
<App />
</FlareErrorBoundary>
Lifecycle hooks
The error boundary provides three hooks that fire at different stages of the error reporting lifecycle. The beforeSubmit and afterSubmit callbacks receive a context object with the following shape:
{
react: {
componentStack: string[]; // Formatted component stack lines
componentStackFrames: { // Parsed frames with source locations
component: string;
file: string | null;
line: number | null;
column: number | null;
}[];
}
}
Both types are exported from @flareapp/react as FlareReactContext (the full object) and ComponentStackFrame (a single entry in componentStackFrames).
The callbacks themselves are not wrapped in a try/catch. If a hook throws, the boundary itself will crash, so keep the logic defensive.
beforeEvaluate
Fires before the component stack context is built. This is the place to attach custom context, tags, or user information to the Flare report:
<FlareErrorBoundary
beforeEvaluate={({ error, errorInfo }) => {
flare.addContext('user', { id: currentUser.id });
flare.addContext('feature-flags', getActiveFlags());
}}
>
<App />
</FlareErrorBoundary>
beforeSubmit
Fires after the component stack context is built but before the error is reported to Flare. The callback receives the context and must return a (possibly modified) context object. Use this to filter or enrich the report context:
<FlareErrorBoundary
beforeSubmit={({ error, errorInfo, context }) => {
return {
...context,
react: {
...context.react,
componentStack: context.react.componentStack.filter(
(line) => !line.includes('ThirdPartyWrapper'),
),
},
};
}}
>
<App />
</FlareErrorBoundary>
afterSubmit
Fires after flare.report() is called. Note that the report is sent asynchronously, so this callback runs after the report is initiated, not after the network request completes. Use this for side effects like logging to a secondary service, showing a toast, or updating app state:
<FlareErrorBoundary
afterSubmit={({ error, errorInfo, context }) => {
console.error('Caught by FlareErrorBoundary:', error);
console.error('Component stack:', errorInfo.componentStack);
console.error('Reported context:', context);
}}
>
<App />
</FlareErrorBoundary>
Filtering errors
The error boundary hooks above are designed for adding context and running side effects; they cannot prevent an error from being reported. To filter or suppress errors, use the core JavaScript client hooks via flare.configure().
Note that the boundary's beforeEvaluate and beforeSubmit are different hooks from flare.configure({ beforeEvaluate, beforeSubmit }) — they share the same name but have different signatures and capabilities. The execution order when both are configured is:
- Boundary
beforeEvaluate(adds context, cannot suppress) flare.report()is called internally, which triggers:- Client
beforeEvaluateviaflare.configure()(can suppress by returningfalse) - Client
beforeSubmitviaflare.configure()(can suppress or modify the report) - Report is sent to Flare
- Boundary
afterSubmit
To suppress specific errors, use the client-level hooks:
flare.configure({
beforeEvaluate: (error) => {
if (error.message.includes('Boring error')) {
return false; // Don't report this error
}
return error;
},
});
See the client hooks documentation for more details.
Errors in event handlers
React error boundaries do not catch errors in event handlers (e.g. onClick, onChange). These errors are caught automatically by the @flareapp/js client via window.onerror, so they will still be reported to Flare. If you're using React 19, the onUncaughtError callback from flareReactErrorHandler also catches these.
Using your own error boundaries
If you have your own error boundary components (e.g. for displaying a custom fallback UI), the error won't bubble up to Flare's error boundary and won't be reported automatically. You can manually report errors to Flare in your own error boundary. Pass the component stack as context so Flare can display it:
import { flare } from '@flareapp/js';
class MyErrorBoundary extends React.Component {
componentDidCatch(error, errorInfo) {
flare.report(error, {
'context.react': {
componentStack: errorInfo.componentStack,
},
});
}
render() {
// your fallback UI
}
}
You can also use a combination of Flare's error boundary at the root of your app and your own error boundaries further down the tree for specific sections.
Component stack context
When the error boundary catches an error, it parses React's component stack and sends both a formatted string array and structured frames in the report context:
{
"context": {
"react": {
"componentStack": [
"at ErrorComponent (http://localhost:5173/src/App.tsx:12:9)",
"at div",
"at App (http://localhost:5173/src/App.tsx:5:3)"
],
"componentStackFrames": [
{
"component": "ErrorComponent",
"file": "http://localhost:5173/src/App.tsx",
"line": 12,
"column": 9
},
{
"component": "div",
"file": null,
"line": null,
"column": null
},
{
"component": "App",
"file": "http://localhost:5173/src/App.tsx",
"line": 5,
"column": 3
}
]
}
}
}
The structured componentStackFrames enable sourcemap resolution and rich dashboard rendering.
Props reference
| Prop | Type | Description |
|---|---|---|
fallback |
ReactNode | (props) => ReactNode |
UI to display when an error is caught. The render function receives error, componentStack (string array), and resetErrorBoundary. |
resetKeys |
unknown[] |
Values that trigger an automatic reset when changed (compared per-index via Object.is, or when the array's length changes). |
beforeEvaluate |
({ error, errorInfo }) => void |
Called before the component stack context is built. errorInfo is React's ErrorInfo (includes componentStack). |
beforeSubmit |
({ error, errorInfo, context }) => FlareReactContext |
Called before submitting. Return a (possibly modified) context. If not provided, the original context is used as-is. |
afterSubmit |
({ error, errorInfo, context }) => void |
Called after flare.report() is called (the report is sent asynchronously). |
onReset |
(error: Error | null) => void |
Called when the error boundary is reset; receives the previous error (or null). |