From 0e39bf756f5782f8b71d43c0bce905f75ac77623 Mon Sep 17 00:00:00 2001 From: Nikita Yutanov Date: Mon, 17 Jul 2023 17:19:27 +0300 Subject: [PATCH] Add error boundary --- idea/frontend/package.json | 1 + idea/frontend/src/app/App.tsx | 11 +++++++-- idea/frontend/src/hooks/useChangeEffect.ts | 23 ++++++++++++------- .../errorFallback/ErrorFallback.module.scss | 8 +++++++ .../shared/ui/errorFallback/ErrorFallback.tsx | 16 +++++++++++++ .../src/shared/ui/errorFallback/index.ts | 3 +++ yarn.lock | 12 ++++++++++ 7 files changed, 64 insertions(+), 10 deletions(-) create mode 100644 idea/frontend/src/shared/ui/errorFallback/ErrorFallback.module.scss create mode 100644 idea/frontend/src/shared/ui/errorFallback/ErrorFallback.tsx create mode 100644 idea/frontend/src/shared/ui/errorFallback/index.ts diff --git a/idea/frontend/package.json b/idea/frontend/package.json index 6893f202c5..12d23d3414 100644 --- a/idea/frontend/package.json +++ b/idea/frontend/package.json @@ -38,6 +38,7 @@ "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-dom": "^18.2.0", + "react-error-boundary": "^4.0.10", "react-final-form": "^6.5.9", "react-final-form-listeners": "^1.0.3", "react-number-format": "^4.9.3", diff --git a/idea/frontend/src/app/App.tsx b/idea/frontend/src/app/App.tsx index c1d859108c..f74d0a8a1c 100644 --- a/idea/frontend/src/app/App.tsx +++ b/idea/frontend/src/app/App.tsx @@ -1,5 +1,6 @@ import { useEffect } from 'react'; -import { useSearchParams } from 'react-router-dom'; +import { useLocation, useSearchParams } from 'react-router-dom'; +import { ErrorBoundary } from 'react-error-boundary'; import { useAccount, useApi } from '@gear-js/react-hooks'; import 'simplebar-react/dist/simplebar.min.css'; @@ -11,12 +12,14 @@ import { MobileDisclaimer } from 'widgets/mobileDisclaimer'; import { Routing } from 'pages'; import { LocalStorage, NODE_ADRESS_URL_PARAM } from 'shared/config'; import { Loader } from 'shared/ui/loader'; +import { ErrorFallback } from 'shared/ui/errorFallback'; import { withProviders } from './providers'; import './App.scss'; const App = withProviders(() => { const { nodeAddress } = useApp(); + const { pathname } = useLocation(); const [searchParams, setSearchParams] = useSearchParams(); const { api, isApiReady } = useApi(); @@ -52,7 +55,11 @@ const App = withProviders(() => {
- {isAppReady ? : } + + {/* key to reset on route change */} + + {isAppReady ? : } +
{isMobileDisclaimerVisible && } diff --git a/idea/frontend/src/hooks/useChangeEffect.ts b/idea/frontend/src/hooks/useChangeEffect.ts index 527ae69e35..c4cb642b34 100644 --- a/idea/frontend/src/hooks/useChangeEffect.ts +++ b/idea/frontend/src/hooks/useChangeEffect.ts @@ -1,16 +1,23 @@ -import { useEffect, useRef } from 'react'; +import { DependencyList, EffectCallback, useEffect, useRef } from 'react'; -export const useChangeEffect = (callback: () => void, dependencies?: unknown[]) => { - const isMounted = useRef(false); +export const useChangeEffect = (callback: EffectCallback, dependencies: DependencyList) => { + const mounted = useRef(false); + + useEffect( + () => () => { + mounted.current = false; + }, + [], + ); useEffect(() => { - if (isMounted.current) { - callback(); + if (mounted.current) { + return callback(); } - return () => { - isMounted.current = true; - }; + mounted.current = true; + return undefined; + // eslint-disable-next-line react-hooks/exhaustive-deps }, dependencies); }; diff --git a/idea/frontend/src/shared/ui/errorFallback/ErrorFallback.module.scss b/idea/frontend/src/shared/ui/errorFallback/ErrorFallback.module.scss new file mode 100644 index 0000000000..ca83af1792 --- /dev/null +++ b/idea/frontend/src/shared/ui/errorFallback/ErrorFallback.module.scss @@ -0,0 +1,8 @@ +.heading { + margin-bottom: 8px; +} + +.error { + margin-bottom: 32px; + color: #f24a4a; +} diff --git a/idea/frontend/src/shared/ui/errorFallback/ErrorFallback.tsx b/idea/frontend/src/shared/ui/errorFallback/ErrorFallback.tsx new file mode 100644 index 0000000000..c6807bc6b7 --- /dev/null +++ b/idea/frontend/src/shared/ui/errorFallback/ErrorFallback.tsx @@ -0,0 +1,16 @@ +import { FallbackProps } from 'react-error-boundary'; + +import { Subheader } from '../subheader'; +import { BackButton } from '../backButton'; +import styles from './ErrorFallback.module.scss'; + +const ErrorFallback = ({ error }: FallbackProps) => ( + <> + +

{error.message}

+ + + +); + +export { ErrorFallback }; diff --git a/idea/frontend/src/shared/ui/errorFallback/index.ts b/idea/frontend/src/shared/ui/errorFallback/index.ts new file mode 100644 index 0000000000..c69b334873 --- /dev/null +++ b/idea/frontend/src/shared/ui/errorFallback/index.ts @@ -0,0 +1,3 @@ +import { ErrorFallback } from './ErrorFallback'; + +export { ErrorFallback }; diff --git a/yarn.lock b/yarn.lock index 92269f5bf7..9f7844d869 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2204,6 +2204,7 @@ __metadata: react-dnd: ^16.0.1 react-dnd-html5-backend: ^16.0.1 react-dom: ^18.2.0 + react-error-boundary: ^4.0.10 react-final-form: ^6.5.9 react-final-form-listeners: ^1.0.3 react-number-format: ^4.9.3 @@ -16743,6 +16744,17 @@ __metadata: languageName: node linkType: hard +"react-error-boundary@npm:^4.0.10": + version: 4.0.10 + resolution: "react-error-boundary@npm:4.0.10" + dependencies: + "@babel/runtime": ^7.12.5 + peerDependencies: + react: ">=16.13.1" + checksum: 4ad4864d2a5fc2264a24d03e83176e6a70d7adbe3c1edbdc5b0bd452a695104bc59456e23b5aea1b9729220672fe46614221daa8b3bd59327968d4aa7eb8bc71 + languageName: node + linkType: hard + "react-error-overlay@npm:^6.0.11": version: 6.0.11 resolution: "react-error-overlay@npm:6.0.11"