1
Fork 0
mirror of https://github.com/Steffo99/festa.git synced 2024-12-22 14:44:21 +00:00

Improve error-related components

This commit is contained in:
Steffo 2022-07-19 19:51:14 +02:00
parent 08ed0f14d3
commit e78532243d
Signed by: steffo
GPG key ID: 6965406171929D01
3 changed files with 57 additions and 16 deletions

View file

@ -1,6 +1,6 @@
import { Component, ErrorInfo, ReactNode } from "react"; import { Component, ErrorInfo, ReactNode } from "react";
import { ViewNotice } from "../views/notice"; import { ViewNotice } from "../views/notice";
import { ErrorBlock, ErrorMain } from "./renderers"; import { ErrorBlock, ErrorInline, ErrorMain, ErrorView } from "./renderers";
export type ErrorBoundaryProps = { export type ErrorBoundaryProps = {
@ -20,7 +20,7 @@ export type ErrorBoundaryState = {
* *
* To be used in `pages/_app`. * To be used in `pages/_app`.
*/ */
export class ErrorBoundaryPage extends Component<ErrorBoundaryProps, ErrorBoundaryState> { export class ErrorBoundaryView extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
constructor(props: ErrorBoundaryProps) { constructor(props: ErrorBoundaryProps) {
super(props) super(props)
this.state = { error: undefined, errorInfo: undefined } this.state = { error: undefined, errorInfo: undefined }
@ -35,11 +35,7 @@ export class ErrorBoundaryPage extends Component<ErrorBoundaryProps, ErrorBounda
render() { render() {
if (this.state.error) { if (this.state.error) {
return ( return (
<ViewNotice <ErrorView text={this.props.text} error={this.state.error} />
notice={
<ErrorMain text={this.props.text} error={this.state.error} />
}
/>
) )
} }
else { else {
@ -76,4 +72,34 @@ export class ErrorBoundaryBlock extends Component<ErrorBoundaryProps, ErrorBound
return this.props.children return this.props.children
} }
} }
}
/**
* Error boundary component which displays an {@link ErrorInline} containing the occurred error inside.
*
* To be used in other components.
*/
export class ErrorBoundaryInline extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
constructor(props: ErrorBoundaryProps) {
super(props)
this.state = { error: undefined, errorInfo: undefined }
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
this.setState(state => {
return { ...state, error, errorInfo }
})
}
render() {
if (this.state.error) {
return (
<ErrorInline text={this.props.text} error={this.state.error} />
)
}
else {
return this.props.children
}
}
} }

View file

@ -5,6 +5,7 @@ import style from "./renderers.module.css"
import mood from "../../../styles/mood.module.css" import mood from "../../../styles/mood.module.css"
import { ComponentPropsWithoutRef, memo } from "react"; import { ComponentPropsWithoutRef, memo } from "react";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
import { ViewNotice } from "../views/notice";
/** /**
@ -149,13 +150,15 @@ ErrorBlock.displayName = "ErrorBlock"
* *
* It displays an inline error {@link FestaIcon}, followed by some **required** text, with the {@link ErrorTrace} below. * It displays an inline error {@link FestaIcon}, followed by some **required** text, with the {@link ErrorTrace} below.
*/ */
export const ErrorMain = memo(({ error, text }: ErrorProps & { text: string }) => { export const ErrorMain = memo(({ error, text }: ErrorProps) => {
return ( return (
<div className={classNames(mood.negative, style.error, style.errorMain)}> <div className={classNames(mood.negative, style.error, style.errorMain)}>
<FestaIcon icon={faCircleExclamation} className={style.errorIcon} /> <FestaIcon icon={faCircleExclamation} className={style.errorIcon} />
<p className={style.errorText}> {text &&
{text} <p className={style.errorText}>
</p> {text}
</p>
}
<pre> <pre>
<ErrorTrace error={error} prettify={false} className={style.errorTrace} /> <ErrorTrace error={error} prettify={false} className={style.errorTrace} />
</pre> </pre>
@ -163,3 +166,15 @@ export const ErrorMain = memo(({ error, text }: ErrorProps & { text: string }) =
) )
}) })
ErrorMain.displayName = "ErrorMain" ErrorMain.displayName = "ErrorMain"
/**
* {@link ViewNotice} component for rendering {@link ErrorMain}.
*/
export const ErrorView = memo((props: ErrorProps) => {
return (
<ViewNotice
notice={<ErrorMain {...props} />}
/>
)
})

View file

@ -3,7 +3,7 @@ import '@fortawesome/fontawesome-svg-core/styles.css'
import { AppProps } from 'next/app' import { AppProps } from 'next/app'
import { appWithTranslation, useTranslation } from 'next-i18next' import { appWithTranslation, useTranslation } from 'next-i18next'
import { AxiosSWRFetcherProvider } from '../components/auth/requests' import { AxiosSWRFetcherProvider } from '../components/auth/requests'
import { ErrorBoundaryPage } from '../components/generic/errors/boundaries' import { ErrorBoundaryView } from '../components/generic/errors/boundaries'
import { AuthContextProvider } from '../components/auth/provider' import { AuthContextProvider } from '../components/auth/provider'
import { PostcardRenderer } from '../components/postcard/renderer' import { PostcardRenderer } from '../components/postcard/renderer'
import { config as fontAwesomeConfig } from '@fortawesome/fontawesome-svg-core' import { config as fontAwesomeConfig } from '@fortawesome/fontawesome-svg-core'
@ -19,22 +19,22 @@ const App = ({ Component, pageProps }: AppProps): JSX.Element => {
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<ErrorBoundaryPage text={t("genericError")}> <ErrorBoundaryView text={t("genericError")}>
<AxiosSWRFetcherProvider> <AxiosSWRFetcherProvider>
<PostcardContextProvider defaultPostcard={defaultPostcard}> <PostcardContextProvider defaultPostcard={defaultPostcard}>
<AuthContextProvider storageKey="auth"> <AuthContextProvider storageKey="auth">
<AxiosSWRFetcherProvider> <AxiosSWRFetcherProvider>
<PostcardRenderer /> <PostcardRenderer />
<ErrorBoundaryPage text={t("genericError")}> <ErrorBoundaryView text={t("genericError")}>
<LoadingBoundaryPage> <LoadingBoundaryPage>
<Component {...pageProps} /> <Component {...pageProps} />
</LoadingBoundaryPage> </LoadingBoundaryPage>
</ErrorBoundaryPage> </ErrorBoundaryView>
</AxiosSWRFetcherProvider> </AxiosSWRFetcherProvider>
</AuthContextProvider> </AuthContextProvider>
</PostcardContextProvider> </PostcardContextProvider>
</AxiosSWRFetcherProvider> </AxiosSWRFetcherProvider>
</ErrorBoundaryPage> </ErrorBoundaryView>
) )
} }