diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index a8597c199ed..3f1406802f7 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -34,6 +34,3 @@ updates:
labels:
- area/dependencies
- team/ui
- ignore:
- - dependency-name: react-error-boundary
- update-types: ["version-update:semver-major"]
diff --git a/js/apps/admin-ui/package.json b/js/apps/admin-ui/package.json
index 6282d325ea5..96170f27ec0 100644
--- a/js/apps/admin-ui/package.json
+++ b/js/apps/admin-ui/package.json
@@ -81,7 +81,6 @@
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
- "react-error-boundary": "^3.1.4",
"react-hook-form": "^7.49.3",
"react-i18next": "^14.0.0",
"react-router-dom": "^6.21.1",
diff --git a/js/apps/admin-ui/src/App.tsx b/js/apps/admin-ui/src/App.tsx
index d1533e3e4ed..a17a9d25ebd 100644
--- a/js/apps/admin-ui/src/App.tsx
+++ b/js/apps/admin-ui/src/App.tsx
@@ -1,6 +1,5 @@
import { Page } from "@patternfly/react-core";
import { PropsWithChildren, Suspense } from "react";
-import { ErrorBoundary } from "react-error-boundary";
import { Outlet } from "react-router-dom";
import { Help, mainPageContentId } from "ui-shared";
@@ -10,6 +9,10 @@ import { AlertProvider } from "./components/alert/Alerts";
import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
import { ErrorRenderer } from "./components/error/ErrorRenderer";
import { KeycloakSpinner } from "./components/keycloak-spinner/KeycloakSpinner";
+import {
+ ErrorBoundaryFallback,
+ ErrorBoundaryProvider,
+} from "./context/ErrorBoundary";
import { RealmsProvider } from "./context/RealmsContext";
import { RecentRealmsProvider } from "./context/RecentRealms";
import { AccessContextProvider } from "./context/access/Access";
@@ -20,21 +23,23 @@ import { SubGroups } from "./groups/SubGroupsContext";
import { AuthWall } from "./root/AuthWall";
const AppContexts = ({ children }: PropsWithChildren) => (
-
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+
);
export const App = () => {
@@ -47,13 +52,7 @@ export const App = () => {
breadcrumb={}
mainContainerId={mainPageContentId}
>
-
- (window.location.href =
- window.location.origin + window.location.pathname)
- }
- >
+
}>
@@ -61,7 +60,7 @@ export const App = () => {
-
+
);
diff --git a/js/apps/admin-ui/src/components/error/ErrorRenderer.tsx b/js/apps/admin-ui/src/components/error/ErrorRenderer.tsx
index 3cd2d224770..57119bd16f1 100644
--- a/js/apps/admin-ui/src/components/error/ErrorRenderer.tsx
+++ b/js/apps/admin-ui/src/components/error/ErrorRenderer.tsx
@@ -5,12 +5,17 @@ import {
AlertVariant,
PageSection,
} from "@patternfly/react-core";
-
-import type { FallbackProps } from "react-error-boundary";
import { useTranslation } from "react-i18next";
-export const ErrorRenderer = ({ error, resetErrorBoundary }: FallbackProps) => {
+import { type FallbackProps } from "../../context/ErrorBoundary";
+
+export const ErrorRenderer = ({ error }: FallbackProps) => {
const { t } = useTranslation();
+
+ const reset = () => {
+ window.location.href = window.location.origin + window.location.pathname;
+ };
+
return (
{
variant={AlertVariant.danger}
title={error.message}
actionClose={
-
+
}
actionLinks={
-
- {t("retry")}
-
+ {t("retry")}
}
>
diff --git a/js/apps/admin-ui/src/context/ErrorBoundary.tsx b/js/apps/admin-ui/src/context/ErrorBoundary.tsx
new file mode 100644
index 00000000000..99d7cd2f510
--- /dev/null
+++ b/js/apps/admin-ui/src/context/ErrorBoundary.tsx
@@ -0,0 +1,76 @@
+import {
+ Component,
+ type ComponentType,
+ type FunctionComponent,
+ type GetDerivedStateFromError,
+ type ReactNode,
+} from "react";
+import { createNamedContext, useRequiredContext } from "ui-shared";
+
+export interface ErrorBoundaryContextValue {
+ error?: Error;
+ showBoundary: (error: Error) => void;
+}
+
+const ErrorBoundaryContext = createNamedContext<
+ ErrorBoundaryContextValue | undefined
+>("ErrorBoundaryContext", undefined);
+
+export const useErrorBoundary = () => useRequiredContext(ErrorBoundaryContext);
+
+export interface ErrorBoundaryProviderProps {
+ children: ReactNode;
+}
+
+export interface ErrorBoundaryProviderState {
+ error?: Error;
+}
+
+export class ErrorBoundaryProvider extends Component<
+ ErrorBoundaryProviderProps,
+ ErrorBoundaryProviderState
+> {
+ state: ErrorBoundaryProviderState = {};
+
+ static getDerivedStateFromError: GetDerivedStateFromError<
+ ErrorBoundaryProviderProps,
+ ErrorBoundaryProviderState
+ > = (error) => {
+ return { error };
+ };
+
+ showBoundary = (error: Error) => {
+ this.setState({ error });
+ };
+
+ render() {
+ return (
+
+ {this.props.children}
+
+ );
+ }
+}
+
+export interface FallbackProps {
+ error: Error;
+}
+
+export interface ErrorBoundaryFallbackProps {
+ fallback: ComponentType;
+ children: ReactNode;
+}
+
+export const ErrorBoundaryFallback: FunctionComponent<
+ ErrorBoundaryFallbackProps
+> = ({ children, fallback: FallbackComponent }) => {
+ const { error } = useErrorBoundary();
+
+ if (error) {
+ return ;
+ }
+
+ return children;
+};
diff --git a/js/apps/admin-ui/src/utils/useFetch.ts b/js/apps/admin-ui/src/utils/useFetch.ts
index a36428e778f..f1ad6b82625 100644
--- a/js/apps/admin-ui/src/utils/useFetch.ts
+++ b/js/apps/admin-ui/src/utils/useFetch.ts
@@ -1,5 +1,5 @@
import { DependencyList, useEffect } from "react";
-import { useErrorHandler } from "react-error-boundary";
+import { useErrorBoundary } from "../context/ErrorBoundary";
/**
* Util function to only set the state when the component is still mounted.
@@ -21,12 +21,11 @@ export function useFetch(
callback: (param: T) => void,
deps?: DependencyList,
) {
- const onError = useErrorHandler();
+ const { showBoundary } = useErrorBoundary();
useEffect(() => {
const controller = new AbortController();
const { signal } = controller;
-
adminClientCall()
.then((result) => {
if (!signal.aborted) {
@@ -35,7 +34,7 @@ export function useFetch(
})
.catch((error) => {
if (!signal.aborted) {
- onError(error);
+ showBoundary(error);
}
});
diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml
index f3fbb921e2f..ce1c09a72c6 100644
--- a/js/pnpm-lock.yaml
+++ b/js/pnpm-lock.yaml
@@ -204,9 +204,6 @@ importers:
react-dropzone:
specifier: ^14.2.3
version: 14.2.3(react@18.2.0)
- react-error-boundary:
- specifier: ^3.1.4
- version: 3.1.4(react@18.2.0)
react-hook-form:
specifier: ^7.49.3
version: 7.49.3(react@18.2.0)
@@ -6101,16 +6098,6 @@ packages:
react: 18.2.0
dev: false
- /react-error-boundary@3.1.4(react@18.2.0):
- resolution: {integrity: sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==}
- engines: {node: '>=10', npm: '>=6'}
- peerDependencies:
- react: '>=16.13.1'
- dependencies:
- '@babel/runtime': 7.23.2
- react: 18.2.0
- dev: false
-
/react-hook-form@7.49.3(react@18.2.0):
resolution: {integrity: sha512-foD6r3juidAT1cOZzpmD/gOKt7fRsDhXXZ0y28+Al1CHgX+AY1qIN9VSIIItXRq1dN68QrRwl1ORFlwjBaAqeQ==}
engines: {node: '>=18', pnpm: '8'}
@@ -7793,7 +7780,6 @@ packages:
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
react-dropzone: 14.2.3(react@18.2.0)
- react-error-boundary: 3.1.4(react@18.2.0)
react-hook-form: 7.49.3(react@18.2.0)
react-i18next: 14.0.0(i18next@23.7.16)(react-dom@18.2.0)(react@18.2.0)
react-router-dom: 6.21.1(react-dom@18.2.0)(react@18.2.0)