From 15c25d79b21ab2d0f5b6de38873d78fe13fd7add Mon Sep 17 00:00:00 2001 From: afc163 Date: Mon, 4 May 2026 23:50:21 +0800 Subject: [PATCH] fix: offlineBanner uses getIntl() and inline network state OfflineBanner is rendered inside rootContainer, which is the outermost wrapper in Umi's provider chain. useModel('network') and useIntl() require provider context (dataflowProvider, i18nProvider) that doesn't exist at this level, causing runtime crashes. Switch to getIntl() (which accesses the global intl singleton) and inline navigator.onLine state. Co-Authored-By: Claude Opus 4.7 --- src/components/OfflineBanner/index.tsx | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/components/OfflineBanner/index.tsx b/src/components/OfflineBanner/index.tsx index 98ee995d..bd279af5 100644 --- a/src/components/OfflineBanner/index.tsx +++ b/src/components/OfflineBanner/index.tsx @@ -1,9 +1,22 @@ -import { useIntl, useModel } from '@umijs/max'; +import { getIntl } from '@umijs/max'; import { Alert } from 'antd'; +import { useEffect, useState } from 'react'; const OfflineBanner: React.FC = () => { - const { isOnline } = useModel('network'); - const intl = useIntl(); + const [isOnline, setIsOnline] = useState( + typeof navigator !== 'undefined' ? navigator.onLine : true, + ); + + useEffect(() => { + const handleOnline = () => setIsOnline(true); + const handleOffline = () => setIsOnline(false); + window.addEventListener('online', handleOnline); + window.addEventListener('offline', handleOffline); + return () => { + window.removeEventListener('online', handleOnline); + window.removeEventListener('offline', handleOffline); + }; + }, []); if (isOnline) return null; @@ -12,7 +25,7 @@ const OfflineBanner: React.FC = () => { type="warning" banner closable={false} - message={intl.formatMessage({ id: 'app.network.offline' })} + message={getIntl().formatMessage({ id: 'app.network.offline' })} /> ); };