From 23fc2c8bd631be41393d6f792549211b0f831385 Mon Sep 17 00:00:00 2001 From: logonoff Date: Thu, 7 May 2026 08:38:00 -0400 Subject: [PATCH] OCPBUGS-85242: Add Suspense fallback to LazyRoutePage Wrap lazy-loaded route components in a React.Suspense with a LoadingBox fallback to show a loading state while plugin pages load. Also import Suspense and LoadingBox, and include pluginName in the extension destructuring so the LoadingBox blame includes the plugin and extension uid. This improves UX when route page components are loaded asynchronously. --- .../console-app/src/hooks/usePluginRoutes.tsx | 11 ++++++++--- frontend/public/components/app.tsx | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/frontend/packages/console-app/src/hooks/usePluginRoutes.tsx b/frontend/packages/console-app/src/hooks/usePluginRoutes.tsx index 1bf3e319efc..27c281ef450 100644 --- a/frontend/packages/console-app/src/hooks/usePluginRoutes.tsx +++ b/frontend/packages/console-app/src/hooks/usePluginRoutes.tsx @@ -1,11 +1,12 @@ import type { FC, ReactElement, ComponentType } from 'react'; -import { useMemo, lazy, useEffect } from 'react'; +import { useMemo, lazy, useEffect, Suspense } from 'react'; import type { RouteProps } from 'react-router'; import { createPath, Route, useLocation } from 'react-router'; import { RoutePage, isRoutePage } from '@console/dynamic-plugin-sdk/src/extensions/pages'; import { useActivePerspective } from '@console/dynamic-plugin-sdk/src/perspective'; import type { LoadedExtension } from '@console/dynamic-plugin-sdk/src/types'; import { useExtensions } from '@console/plugin-sdk/src/api/useExtensions'; +import { LoadingBox } from '@console/shared/src/components/loading/LoadingBox'; const isRoutePageExtensionActive: IsRouteExtensionActive = (extension, activePerspective) => (extension.properties.perspective ?? activePerspective) === activePerspective; @@ -14,7 +15,7 @@ const isRoutePageExtensionActive: IsRouteExtensionActive = (extension, activePer const lazyComponentCache = new Map>>(); const LazyRoutePage: FC = ({ extension }) => { - const { uid, properties } = extension; + const { pluginName, uid, properties } = extension; const { component } = properties; const LazyComponent = useMemo(() => { if (!lazyComponentCache.has(uid)) { @@ -29,7 +30,11 @@ const LazyRoutePage: FC = ({ extension }) => { return lazyComponentCache.get(uid); }, [uid, component]); - return ; + return ( + }> + + + ); }; const InactiveRoutePage: FC = ({ diff --git a/frontend/public/components/app.tsx b/frontend/public/components/app.tsx index d7d3f332e6a..9a89b0daf56 100644 --- a/frontend/public/components/app.tsx +++ b/frontend/public/components/app.tsx @@ -374,7 +374,7 @@ const AppRouter: FC = () => { ); return ( - + {/* Treat the authentication error page as a standalone route.