Skip to content

Commit 801e41a

Browse files
committed
refactor(tanstackstart-react): Remove passthrough ErrorBoundary from server and cloudflare entries
ErrorBoundary is a React client rendering concept that does not function during SSR. Exporting a no-op passthrough from server entries is semantically incorrect and may give users false confidence in error handling. This aligns with the React Router package which does not export ErrorBoundary from its server entry point. The cloudflare entry now re-exports the real @sentry/react ErrorBoundary via `export * from '../client'` instead of overriding it with a passthrough.
1 parent d386a4d commit 801e41a

File tree

4 files changed

+5
-80
lines changed

4 files changed

+5
-80
lines changed

packages/tanstackstart-react/src/cloudflare/index.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,3 @@ export * from '../common';
77
export { wrapFetchWithSentry } from '../server/wrapFetchWithSentry';
88
export { wrapMiddlewaresWithSentry } from '../server/middleware';
99
export { sentryGlobalRequestMiddleware, sentryGlobalFunctionMiddleware } from '../server/globalMiddleware';
10-
11-
/**
12-
* A passthrough error boundary for the server that doesn't depend on any react. Error boundaries don't catch SSR errors
13-
* so they should simply be a passthrough.
14-
*/
15-
export const ErrorBoundary = (props: React.PropsWithChildren<unknown>): React.ReactNode => {
16-
if (!props.children) {
17-
return null;
18-
}
19-
20-
if (typeof props.children === 'function') {
21-
return (props.children as () => React.ReactNode)();
22-
}
23-
24-
return props.children;
25-
};
26-
27-
/**
28-
* A passthrough error boundary wrapper for the server that doesn't depend on any react. Error boundaries don't catch
29-
* SSR errors so they should simply be a passthrough.
30-
*/
31-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
32-
export function withErrorBoundary<P extends Record<string, any>>(
33-
WrappedComponent: React.ComponentType<P>,
34-
): React.FC<P> {
35-
return WrappedComponent as React.FC<P>;
36-
}

packages/tanstackstart-react/src/index.types.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ export declare const contextLinesIntegration: typeof clientSdk.contextLinesInteg
2222
export declare const getDefaultIntegrations: (options: Options) => Integration[];
2323
export declare const defaultStackParser: StackParser;
2424

25-
export declare const ErrorBoundary: typeof clientSdk.ErrorBoundary;
26-
export declare const withErrorBoundary: typeof clientSdk.withErrorBoundary;
27-
2825
export declare const logger: typeof clientSdk.logger | typeof serverSdk.logger;
2926

3027
export declare const growthbookIntegration: typeof clientSdk.growthbookIntegration;

packages/tanstackstart-react/src/server/index.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,30 +23,3 @@ export function tanstackRouterBrowserTracingIntegration(
2323
setup() {},
2424
};
2525
}
26-
27-
/**
28-
* A passthrough error boundary for the server that doesn't depend on any react. Error boundaries don't catch SSR errors
29-
* so they should simply be a passthrough.
30-
*/
31-
export const ErrorBoundary = (props: React.PropsWithChildren<unknown>): React.ReactNode => {
32-
if (!props.children) {
33-
return null;
34-
}
35-
36-
if (typeof props.children === 'function') {
37-
return (props.children as () => React.ReactNode)();
38-
}
39-
40-
return props.children;
41-
};
42-
43-
/**
44-
* A passthrough error boundary wrapper for the server that doesn't depend on any react. Error boundaries don't catch
45-
* SSR errors so they should simply be a passthrough.
46-
*/
47-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
48-
export function withErrorBoundary<P extends Record<string, any>>(
49-
WrappedComponent: React.ComponentType<P>,
50-
): React.FC<P> {
51-
return WrappedComponent as React.FC<P>;
52-
}

packages/tanstackstart-react/test/cloudflare/index.test.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ErrorBoundary as ReactErrorBoundary, withErrorBoundary as reactWithErrorBoundary } from '@sentry/react';
12
import { describe, expect, it } from 'vitest';
23
import * as CloudflareExports from '../../src/cloudflare/index';
34

@@ -29,32 +30,13 @@ describe('Cloudflare entrypoint', () => {
2930
it('exports wrapFetchWithSentry', () => {
3031
expect(typeof CloudflareExports.wrapFetchWithSentry).toBe('function');
3132
});
32-
});
33-
34-
describe('ErrorBoundary', () => {
35-
it('is a passthrough that returns children directly', () => {
36-
const children = 'test child';
37-
const result = CloudflareExports.ErrorBoundary({ children });
38-
expect(result).toBe('test child');
39-
});
4033

41-
it('returns null when no children are provided', () => {
42-
const result = CloudflareExports.ErrorBoundary({});
43-
expect(result).toBeNull();
34+
it('exports ErrorBoundary from @sentry/react', () => {
35+
expect(CloudflareExports.ErrorBoundary).toBe(ReactErrorBoundary);
4436
});
4537

46-
it('calls children when children is a function', () => {
47-
const children = () => 'function result';
48-
const result = CloudflareExports.ErrorBoundary({ children });
49-
expect(result).toBe('function result');
50-
});
51-
});
52-
53-
describe('withErrorBoundary', () => {
54-
it('is a passthrough that returns the original component', () => {
55-
const MockComponent = () => null;
56-
const result = CloudflareExports.withErrorBoundary(MockComponent);
57-
expect(result).toBe(MockComponent);
38+
it('exports withErrorBoundary from @sentry/react', () => {
39+
expect(CloudflareExports.withErrorBoundary).toBe(reactWithErrorBoundary);
5840
});
5941
});
6042
});

0 commit comments

Comments
 (0)