From e48b890fd71b3899a45adf7436ab76cc1c1d0b16 Mon Sep 17 00:00:00 2001 From: Andrei Dekterev Date: Fri, 31 Mar 2023 19:38:19 +0700 Subject: [PATCH] feat(errorboundary): add error boundaryComponent --- src/components/Error/index.tsx | 38 ++++++++++++++++++++ src/components/Error/styled.tsx | 17 +++++++++ src/components/ErrorBoundary/index.tsx | 50 ++++++++++++++++++++++++++ src/components/SimplePopup/index.tsx | 10 ++++-- src/config/lexics/indexLexics.tsx | 1 + src/features/App/index.tsx | 11 +++--- 6 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 src/components/Error/index.tsx create mode 100644 src/components/Error/styled.tsx create mode 100644 src/components/ErrorBoundary/index.tsx diff --git a/src/components/Error/index.tsx b/src/components/Error/index.tsx new file mode 100644 index 00000000..a13e1e81 --- /dev/null +++ b/src/components/Error/index.tsx @@ -0,0 +1,38 @@ +import { useEffect } from 'react' + +import { FadeIn } from 'features/Animation' +import { T9n } from 'features/T9n' + +import { useToggle } from 'hooks' + +import { WrapperError } from './styled' + +type ErrorInfo = { + error?: string, +} +export const Error = ({ error }: ErrorInfo) => { + const { + close, + isOpen, + open, + } = useToggle() + + useEffect(() => { + open() + const timeOut = setTimeout(close, 5000) + return () => { + clearInterval(timeOut) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []) + + return ( + isOpen ? ( + + + {error ?? } + + + ) : null + ) +} diff --git a/src/components/Error/styled.tsx b/src/components/Error/styled.tsx new file mode 100644 index 00000000..fde3a01b --- /dev/null +++ b/src/components/Error/styled.tsx @@ -0,0 +1,17 @@ +import styled from 'styled-components/macro' + +export const WrapperError = styled.div` + position: fixed; + top: 20px; + right: 20px; + width: 390px; + max-height: 500px; + border-radius: 10px; + background-color: #333333; + color: white; + padding: 20px; + font-size: 0.8rem; + text-align: center; + z-index: 1000000; + white-space: pre-wrap; +` diff --git a/src/components/ErrorBoundary/index.tsx b/src/components/ErrorBoundary/index.tsx new file mode 100644 index 00000000..b3a27e45 --- /dev/null +++ b/src/components/ErrorBoundary/index.tsx @@ -0,0 +1,50 @@ +// eslint-disable react/destructuring-assignment + +import { Component } from 'react' + +import type{ ErrorInfo, ReactNode } from 'react' + +import { Error } from '../Error' + +interface Props { + children?: ReactNode, +} + +interface State { + hasError: boolean, +} + +class ErrorBoundary extends Component { + // eslint-disable-next-line react/state-in-constructor + public state: State = { + hasError: false, + } + + public static getDerivedStateFromError(_: Error): State { + // Update state so the next render will show the fallback UI. + return { hasError: true } + } + + public componentDidCatch(error: Error, errorInfo: ErrorInfo) { + // eslint-disable-next-line no-console + console.error( + 'Uncaught error:', + error, + errorInfo, + ) + } + + public render() { + const { hasError } = this.state + const { children } = this.props + + return ( + <> + {hasError && } + {children} + + ) + } +} + +export default ErrorBoundary diff --git a/src/components/SimplePopup/index.tsx b/src/components/SimplePopup/index.tsx index 1ad02429..e848daff 100644 --- a/src/components/SimplePopup/index.tsx +++ b/src/components/SimplePopup/index.tsx @@ -15,6 +15,7 @@ import { type Props = { buttonName?: string, + children?: ReactNode, headerName?: string, icon?: ReactNode, isModalOpen: boolean, @@ -26,6 +27,7 @@ type Props = { export const SimplePopup = (props: Props) => { const { buttonName, + children, headerName, icon, isModalOpen, @@ -47,9 +49,11 @@ export const SimplePopup = (props: Props) => { - - - + {children || ( + + + + )} {buttonName && ( diff --git a/src/config/lexics/indexLexics.tsx b/src/config/lexics/indexLexics.tsx index bb6aea9e..bf1e822a 100644 --- a/src/config/lexics/indexLexics.tsx +++ b/src/config/lexics/indexLexics.tsx @@ -163,6 +163,7 @@ export const indexLexics = { loading: 3527, logout: 4306, lost_connection: 15699, + main_error: 20101, match_status_finished: 12985, match_status_live: 12984, match_status_soon: 12986, diff --git a/src/features/App/index.tsx b/src/features/App/index.tsx index 093c073e..af66da71 100644 --- a/src/features/App/index.tsx +++ b/src/features/App/index.tsx @@ -23,6 +23,7 @@ import { GlobalStyles } from 'features/GlobalStyles' import { Theme } from 'features/Theme' import { UnavailableText } from 'components/UnavailableText' +import ErrorBoundary from 'components/ErrorBoundary' import { AuthenticatedApp } from './AuthenticatedApp' import { useAuthStore } from '../AuthStore' @@ -40,10 +41,12 @@ const Main = () => { // имеется действующий токен return isToken ? ( - - - - + + + + + + ) : null }