Skip to content

Commit e0a21b4

Browse files
committed
refactor: scope lazy modal chunk failures with LazyModalSlot wrapper
1 parent 2e649a2 commit e0a21b4

2 files changed

Lines changed: 25 additions & 21 deletions

File tree

src/GlobalModals.tsx

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import React, {startTransition, Suspense, useEffect, useState} from 'react';
2-
import {ErrorBoundary as ReactErrorBoundary} from 'react-error-boundary';
1+
import React, {startTransition, useEffect, useState} from 'react';
32
import DelegateNoAccessModalProvider from './components/DelegateNoAccessModalProvider';
43
import EmojiPicker from './components/EmojiPicker/EmojiPicker';
54
import GrowlNotification from './components/GrowlNotification';
5+
import LazyModalSlot from './components/LazyModalSlot';
66
import * as EmojiPickerAction from './libs/actions/EmojiPickerAction';
77
import {growlRef} from './libs/Growl';
8-
import Log from './libs/Log';
98
import * as ReportActionContextMenu from './pages/inbox/report/ContextMenu/ReportActionContextMenu';
109

1110
const LazyPopoverReportActionContextMenu = React.lazy(() => import('./pages/inbox/report/ContextMenu/PopoverReportActionContextMenu'));
@@ -17,24 +16,6 @@ const LazyProactiveAppReviewModalManager = React.lazy(() => import('./components
1716
// guaranteeing mount even if the main thread never becomes idle.
1817
const IDLE_CALLBACK_TIMEOUT_MS = 2000;
1918

20-
const logModalChunkFailure = (error: Error, info: {componentStack?: string | null}) =>
21-
Log.alert(`[GlobalModals] lazy chunk failure - ${error.message}`, {componentStack: info.componentStack ?? undefined}, false);
22-
23-
/**
24-
* Wraps a lazy modal in its own ErrorBoundary + Suspense pair so a chunk-load failure
25-
* (or unrelated load latency) in one modal cannot tear down sibling modals or the rest of GlobalModals.
26-
*/
27-
function LazyModalSlot({children}: {children: React.ReactNode}) {
28-
return (
29-
<ReactErrorBoundary
30-
fallback={null}
31-
onError={logModalChunkFailure}
32-
>
33-
<Suspense fallback={null}>{children}</Suspense>
34-
</ReactErrorBoundary>
35-
);
36-
}
37-
3819
/**
3920
* Renders global modals and overlays that are mounted once at the top level.
4021
*/

src/components/LazyModalSlot.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React, {Suspense} from 'react';
2+
import {ErrorBoundary as ReactErrorBoundary} from 'react-error-boundary';
3+
import Log from '@libs/Log';
4+
5+
const logModalChunkFailure = (error: Error, info: {componentStack?: string | null}) =>
6+
Log.alert(`[GlobalModals] lazy chunk failure - ${error.message}`, {componentStack: info.componentStack ?? undefined}, false);
7+
8+
/**
9+
* Wraps a lazy-loaded child in its own ErrorBoundary + Suspense pair so a chunk-load failure
10+
* (or unrelated load latency) in one slot cannot tear down sibling slots or surrounding components.
11+
*/
12+
function LazyModalSlot({children}: {children: React.ReactNode}) {
13+
return (
14+
<ReactErrorBoundary
15+
fallback={null}
16+
onError={logModalChunkFailure}
17+
>
18+
<Suspense fallback={null}>{children}</Suspense>
19+
</ReactErrorBoundary>
20+
);
21+
}
22+
23+
export default LazyModalSlot;

0 commit comments

Comments
 (0)