Skip to content
Open
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
92 changes: 90 additions & 2 deletions playground/react/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import { flare } from '../shared/initFlare';
import { AsyncErrorButton } from './AsyncErrorButton';
import { BuggyComponent } from './BuggyComponent';
import { Button } from './Button';
import { ConditionallyBuggyComponent } from './ConditionallyBuggyComponent';

export function App() {
const [showBuggy, setShowBuggy] = useState(false);
const [showStaticFallback, setShowStaticFallback] = useState(false);
const [showResetKeysDemo, setShowResetKeysDemo] = useState(false);
const [shouldThrow, setShouldThrow] = useState(true);
const [resetCount, setResetCount] = useState(0);

return (
<>
Expand All @@ -31,12 +36,17 @@ export function App() {
{showBuggy && (
<FlareErrorBoundary
resetKeys={[]}
afterSubmit={() => console.log('FlareErrorBoundary afterSubmit callback')}
onReset={() => console.log('FlareErrorBoundary onReset callback')}
beforeEvaluate={() => {
flare.addContext('playground', 'test');
flare.addContext('showBuggy', showBuggy);
}}
beforeSubmit={({ error, context }) => {
console.log('FlareErrorBoundary beforeSubmit callback', error.message);
context.react.componentStack = [...context.react.componentStack, 'injected by beforeSubmit'];
return context;
}}
afterSubmit={() => console.log('FlareErrorBoundary afterSubmit callback')}
onReset={() => console.log('FlareErrorBoundary onReset callback')}
fallback={({ error, resetErrorBoundary }) => (
<div className="space-y-1">
<p>Something went wrong: {error.message}</p>
Expand Down Expand Up @@ -69,6 +79,84 @@ export function App() {
>
flare.report() from component
</Button>
<Button
onClick={() => {
console.log('Throwing a string (non-Error) in onClick handler');
throw 'This is a string throw, not an Error object';
}}
>
Throw string in onClick
</Button>
<Button
onClick={() => {
console.log('Triggering static fallback boundary');
setShowStaticFallback(true);
}}
>
Trigger static fallback
</Button>
<Button
onClick={() => {
setShowStaticFallback(false);
console.log('Reset static fallback state');
}}
>
Reset static fallback
</Button>
{showStaticFallback && (
<FlareErrorBoundary
fallback={
<p className="text-sm text-red-600">
Static fallback: something went wrong (no reset available).
</p>
}
afterSubmit={({ error }) => console.log('Static fallback boundary afterSubmit', error.message)}
>
<BuggyComponent />
</FlareErrorBoundary>
)}
<Button
onClick={() => {
console.log('Triggering resetKeys demo');
setShouldThrow(true);
setShowResetKeysDemo(true);
}}
>
Trigger resetKeys demo
</Button>
<Button
onClick={() => {
console.log('Fixing component and changing resetKeys to auto-reset boundary');
setShouldThrow(false);
setResetCount((c) => c + 1);
}}
>
Fix and reset via resetKeys
</Button>
<Button
onClick={() => {
setShowResetKeysDemo(false);
setShouldThrow(true);
setResetCount(0);
console.log('Reset resetKeys demo state');
}}
>
Reset resetKeys demo
</Button>
{showResetKeysDemo && (
<FlareErrorBoundary
resetKeys={[resetCount]}
onReset={(error) => console.log('resetKeys boundary onReset', error?.message ?? 'no error')}
afterSubmit={({ error }) => console.log('resetKeys boundary afterSubmit', error.message)}
fallback={({ error }) => (
<p className="text-sm text-red-600">
resetKeys boundary caught: {error.message} (click "Fix and reset via resetKeys" to recover)
</p>
)}
>
<ConditionallyBuggyComponent shouldThrow={shouldThrow} />
</FlareErrorBoundary>
)}
</>
);
}
7 changes: 7 additions & 0 deletions playground/react/ConditionallyBuggyComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function ConditionallyBuggyComponent({ shouldThrow }: { shouldThrow: boolean }) {
if (shouldThrow) {
throw new Error('ConditionallyBuggyComponent render error');
}

return <p className="text-sm text-green-700">ConditionallyBuggyComponent rendered successfully!</p>;
}
23 changes: 12 additions & 11 deletions playground/react/main.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { flareReactErrorHandler } from '@flareapp/react';
import { createRoot } from 'react-dom/client';

import { createSidebar } from '../shared/createSidebar';
Expand All @@ -10,20 +11,20 @@ initFlare(import.meta.env.VITE_FLARE_REACT_KEY);
createSidebar();

createRoot(document.querySelector('#root')!, {
// Not using callbacks here because FlareErrorBoundary already reports caught errors. Using both would result in duplicate reports.
// Not using onCaughtError here because FlareErrorBoundary already reports caught errors. Using both would result in duplicate reports.
// onCaughtError: flareReactErrorHandler({
// afterSubmit: ({ error, errorInfo }) => {
// console.log('onCaughtError', error, errorInfo.componentStack);
// },
// }),
// onUncaughtError: flareReactErrorHandler({
// afterSubmit: ({ error, errorInfo }) => {
// console.log('onUncaughtError', error, errorInfo.componentStack);
// },
// }),
// onRecoverableError: flareReactErrorHandler({
// afterSubmit: ({ error, errorInfo }) => {
// console.log('onRecoverableError', error, errorInfo.componentStack);
// },
// }),
onUncaughtError: flareReactErrorHandler({
afterSubmit: ({ error, errorInfo }) => {
console.log('onUncaughtError', error, errorInfo.componentStack);
},
}),
onRecoverableError: flareReactErrorHandler({
afterSubmit: ({ error, errorInfo }) => {
console.log('onRecoverableError', error, errorInfo.componentStack);
},
}),
}).render(<App />);
Loading