feat: new error boundary component

This commit is contained in:
MTG2000
2022-09-13 14:05:38 +03:00
parent dcf6aa53e6
commit 0af7ddb194
14 changed files with 127 additions and 10 deletions

24
package-lock.json generated
View File

@@ -71,6 +71,7 @@
"react-copy-to-clipboard": "^5.1.0",
"react-datepicker": "^4.7.0",
"react-dom": "^18.0.0",
"react-error-boundary": "^3.1.4",
"react-file-drop": "^3.1.4",
"react-helmet": "^6.1.0",
"react-hook-form": "^7.30.0",
@@ -62242,6 +62243,21 @@
"node": ">=0.10.0"
}
},
"node_modules/react-error-boundary": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz",
"integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==",
"dependencies": {
"@babel/runtime": "^7.12.5"
},
"engines": {
"node": ">=10",
"npm": ">=6"
},
"peerDependencies": {
"react": ">=16.13.1"
}
},
"node_modules/react-error-overlay": {
"version": "6.0.11",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
@@ -118430,6 +118446,14 @@
}
}
},
"react-error-boundary": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-3.1.4.tgz",
"integrity": "sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==",
"requires": {
"@babel/runtime": "^7.12.5"
}
},
"react-error-overlay": {
"version": "6.0.11",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",

View File

@@ -66,6 +66,7 @@
"react-copy-to-clipboard": "^5.1.0",
"react-datepicker": "^4.7.0",
"react-dom": "^18.0.0",
"react-error-boundary": "^3.1.4",
"react-file-drop": "^3.1.4",
"react-helmet": "^6.1.0",
"react-hook-form": "^7.30.0",

View File

@@ -1,5 +1,5 @@
import React, { Component, ErrorInfo, ReactNode } from "react";
import ErrorMessage from "../ErrorMessage/ErrorMessage";
import ErrorMessage from "../Errors/ErrorMessage/ErrorMessage";
interface Props {
place?: string

View File

@@ -0,0 +1,21 @@
import { ComponentStory, ComponentMeta } from '@storybook/react';
import ErrorCard from './ErrorCard';
export default {
title: 'Shared/ErrorCard',
component: ErrorCard,
} as ComponentMeta<typeof ErrorCard>;
const Template: ComponentStory<typeof ErrorCard> = (args) => <ErrorCard {...args} />;
export const Default = Template.bind({});
Default.args = {
error: {
name: "Error Name",
message: "Error Message",
}
}

View File

@@ -0,0 +1,40 @@
import { useToggle } from "@react-hookz/web";
import { FallbackProps } from "react-error-boundary";
import { RiErrorWarningFill } from "react-icons/ri";
import Button from "src/Components/Button/Button";
import Card from "src/Components/Card/Card";
export default function ErrorCard({ error, resetErrorBoundary }: FallbackProps) {
const [showDetails, toggleDetails] = useToggle(false)
return (
<Card className="!border-red-500">
<div className="max-w-[60ch] mx-auto flex flex-col justify-center items-center gap-24">
<div className="text-h1 text-red-400 "><RiErrorWarningFill /></div>
<p className="text-body4 text-center text-gray-600">Ooops... <br /> Looks like something unexpected went wrong, please check your internet connection & try again.</p>
<div className="flex flex-col gap-12">
<Button onClick={() => resetErrorBoundary()} color='black'>Try Again</Button>
<Button href="/" color='gray' variant="text" size="sm" className="">Back to homepage</Button>
</div>
<div className="self-start">
<button className="text-gray-400 text-body5 underline" onClick={() => toggleDetails()}>{showDetails ? "Hide" : "Show"} error details</button>
{showDetails &&
<div className="mt-16 text-gray-600">
<p className="text-body3 text-gray-800">{error.name}</p>
<p className="text-body4">{error.message}</p>
<p className="text-body4 whitespace-pre-line">{error.stack}</p>
</div>
}
</div>
</div>
</Card>
)
}

View File

@@ -0,0 +1,18 @@
import React from 'react'
import { Helmet } from 'react-helmet'
import { FallbackProps } from 'react-error-boundary'
import ErrorCard from '../ErrorCard/ErrorCard'
export default function ErrorPage({ error, resetErrorBoundary }: FallbackProps) {
return (
<div className="">
<Helmet>
<title>{`Something went wrong...`}</title>
</Helmet>
<div className="page-container">
<ErrorCard error={error} resetErrorBoundary={resetErrorBoundary} />
</div>
</div>
)
}

View File

@@ -10,6 +10,7 @@ import Button from "src/Components/Button/Button";
import { FiCopy } from "react-icons/fi";
import useCopyToClipboard from "src/utils/hooks/useCopyToClipboard";
import { getPropertyFromUnknown, trimText, } from "src/utils/helperFunctions";
import { useErrorHandler } from 'react-error-boundary';
@@ -33,7 +34,7 @@ export const useLnurlQuery = () => {
const doFetch = async () => {
const res = await fetchLnurlAuth();
if (!res?.encoded)
setError(true)
setError(new Error("Response doesn't contain data"))
else {
setLoading(false);
setData({
@@ -43,7 +44,7 @@ export const useLnurlQuery = () => {
timeOut = setTimeout(doFetch, 1000 * 60 * 2)
}
}
doFetch()
doFetch().catch(err => setError(err));
return () => clearTimeout(timeOut)
}, [])
@@ -64,8 +65,9 @@ export default function LoginPage() {
const canFetchIsLogged = useRef(true)
const { loadingLnurl, data: { lnurl, session_token }, error } = useLnurlQuery();
const clipboard = useCopyToClipboard()
useErrorHandler(error)
const clipboard = useCopyToClipboard()
useEffect(() => {
@@ -198,6 +200,8 @@ export default function LoginPage() {
</div>;
return (
<>
<Helmet>

View File

@@ -1,5 +1,5 @@
import { useParams, Navigate } from 'react-router-dom'
import ErrorMessage from 'src/Components/ErrorMessage/ErrorMessage';
import ErrorMessage from 'src/Components/Errors/ErrorMessage/ErrorMessage';
import { useCategoryPageQuery } from 'src/graphql';
import HeaderImage from './HeaderImage/HeaderImage';
import ProjectsGrid from './ProjectsGrid/ProjectsGrid';

View File

@@ -1,6 +1,6 @@
import ASSETS from 'src/assets';
import ErrorMessage from 'src/Components/ErrorMessage/ErrorMessage';
import ErrorMessage from 'src/Components/Errors/ErrorMessage/ErrorMessage';
import HeaderImage from 'src/features/Projects/pages/CategoryPage/HeaderImage/HeaderImage';
import ProjectsGrid from 'src/features/Projects/pages/CategoryPage/ProjectsGrid/ProjectsGrid';
import { Helmet } from "react-helmet";

View File

@@ -13,7 +13,7 @@ import { Wallet_Service } from 'src/services'
import { useProjectDetailsQuery } from 'src/graphql';
import Lightbox from 'src/Components/Lightbox/Lightbox'
import linkifyHtml from 'linkify-html';
import ErrorMessage from 'src/Components/ErrorMessage/ErrorMessage';
import ErrorMessage from 'src/Components/Errors/ErrorMessage/ErrorMessage';
import { setVoteAmount } from 'src/redux/features/vote.slice';
import { numberFormatter } from 'src/utils/helperFunctions';
import { MEDIA_QUERIES } from 'src/utils/theme';

View File

@@ -13,8 +13,9 @@ import { ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import 'react-loading-skeleton/dist/skeleton.css'
import THEME from './theme';
import ErrorBoundary from 'src/Components/ErrorBoundary/ErrorBoundary';
import { NotificationsService } from 'src/services';
import ErrorPage from 'src/Components/Errors/ErrorPage/ErrorPage';
import { ErrorBoundary } from 'react-error-boundary';
THEME.injectStyles();
let basename = '/';
@@ -45,7 +46,9 @@ export default function Wrapper(props: any) {
return (
<>
<ErrorBoundary place='app'>
<ErrorBoundary
FallbackComponent={ErrorPage}
>
<ApolloProvider client={apolloClient}>
<Provider store={store}>
<BrowserRouter basename={basename}>

View File

@@ -1,9 +1,15 @@
import { ErrorBoundary } from 'react-error-boundary';
import { Outlet, } from 'react-router-dom';
import ErrorPage from 'src/Components/Errors/ErrorPage/ErrorPage';
import Navbar from "src/Components/Navbar/Navbar";
export const NavbarLayout = () => {
return <>
<Navbar />
<Outlet />
<ErrorBoundary
FallbackComponent={ErrorPage}
>
<Outlet />
</ErrorBoundary>
</>
};