From 84d9591f3f36f7eeb20aa75b63ba25f359964fd5 Mon Sep 17 00:00:00 2001 From: devleejb Date: Tue, 23 Jan 2024 12:58:25 +0900 Subject: [PATCH 1/4] Add error page --- frontend/src/App.tsx | 1 + .../src/components/common/CodePairError.tsx | 19 +++++++++++++++++++ frontend/src/routes.tsx | 16 +++++++++++++++- 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 frontend/src/components/common/CodePairError.tsx diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index feb453f5..60dc8715 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -10,6 +10,7 @@ import { useMemo } from "react"; import { selectConfig } from "./store/configSlice"; import axios from "axios"; import { routes } from "./routes"; +import CodePairErrorBoundary from "./components/common/CodePairError"; const router = createBrowserRouter(routes); diff --git a/frontend/src/components/common/CodePairError.tsx b/frontend/src/components/common/CodePairError.tsx new file mode 100644 index 00000000..773f12bd --- /dev/null +++ b/frontend/src/components/common/CodePairError.tsx @@ -0,0 +1,19 @@ +import { Stack, Typography } from "@mui/material"; +import { isRouteErrorResponse, useRouteError } from "react-router-dom"; + +function CodePairError() { + const error = useRouteError(); + + return ( + + + Something went wrong + {isRouteErrorResponse(error) && ( + Status Code: {error.status} + )} + + + ); +} + +export default CodePairError; diff --git a/frontend/src/routes.tsx b/frontend/src/routes.tsx index 99acf738..9d7ce6ac 100644 --- a/frontend/src/routes.tsx +++ b/frontend/src/routes.tsx @@ -7,6 +7,18 @@ import WorkspaceLayout from "./components/layouts/WorkspaceLayout"; import GuestRoute from "./components/common/GuestRoute"; import PrivateRoute from "./components/common/PrivateRoute"; import WorkspaceIndex from "./pages/workspace/Index"; +import CodePairError from "./components/common/CodePairError"; + +interface CodePairRoute { + path: string; + accessType: AccessType; + element: JSX.Element; + errorElement?: JSX.Element; + children?: { + path: string; + element: JSX.Element; + }[]; +} const enum AccessType { PRIVATE, // Authroized user can access only @@ -14,7 +26,7 @@ const enum AccessType { GUEST, // Not authorized user can access only } -const codePairRoutes = [ +const codePairRoutes: Array = [ { path: "", accessType: AccessType.GUEST, @@ -63,6 +75,8 @@ const injectProtectedRoute = (routes: typeof codePairRoutes) => { route.element = {route.element}; } + route.errorElement = ; + return route; }); }; From 75097d8a683ea61df0a14dc56703b065c172a20f Mon Sep 17 00:00:00 2001 From: devleejb Date: Tue, 23 Jan 2024 13:11:23 +0900 Subject: [PATCH 2/4] Add error handler --- frontend/src/App.tsx | 35 +++++++++++++++++++++------ frontend/src/hooks/useErrorHandler.ts | 7 ++++++ frontend/src/main.tsx | 9 +------ 3 files changed, 35 insertions(+), 16 deletions(-) create mode 100644 frontend/src/hooks/useErrorHandler.ts diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 60dc8715..d1dc6daf 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -6,11 +6,13 @@ import "./App.css"; import { Box, CssBaseline, ThemeProvider, createTheme, useMediaQuery } from "@mui/material"; import { useSelector } from "react-redux"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; -import { useMemo } from "react"; +import { useEffect, useMemo } from "react"; import { selectConfig } from "./store/configSlice"; import axios from "axios"; import { routes } from "./routes"; -import CodePairErrorBoundary from "./components/common/CodePairError"; +import { QueryCache, QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import AuthProvider from "./providers/AuthProvider"; +import { useErrorHandler } from "./hooks/useErrorHandler"; const router = createBrowserRouter(routes); @@ -33,14 +35,31 @@ function App() { }, }); }, [config.theme, prefersDarkMode]); + const handleError = useErrorHandler(); + const queryClient = useMemo(() => { + return new QueryClient({ + queryCache: new QueryCache({ + onError: handleError, + }), + defaultOptions: { + mutations: { + onError: handleError, + }, + }, + }); + }, []); return ( - - - - - - + + + + + + + + + + ); } diff --git a/frontend/src/hooks/useErrorHandler.ts b/frontend/src/hooks/useErrorHandler.ts new file mode 100644 index 00000000..74673694 --- /dev/null +++ b/frontend/src/hooks/useErrorHandler.ts @@ -0,0 +1,7 @@ +import { useCallback } from "react"; + +export function useErrorHandler() { + const handleError = useCallback((error: Error) => {}, []); + + return handleError; +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index a793cbfb..f59de3d2 100755 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -6,21 +6,14 @@ import { store } from "./store/store"; import { Provider } from "react-redux"; import { PersistGate } from "redux-persist/integration/react"; import { persistStore } from "redux-persist"; -import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import AuthProvider from "./providers/AuthProvider"; const persistor = persistStore(store); -const queryClient = new QueryClient(); ReactDOM.createRoot(document.getElementById("root")!).render( - - - - - + From 5ed1efcc55b812ef8ac77f0f532b6b15fcbad8aa Mon Sep 17 00:00:00 2001 From: devleejb Date: Tue, 23 Jan 2024 13:19:53 +0900 Subject: [PATCH 3/4] Add notistack for query error --- frontend/package-lock.json | 37 +++++++++++++++++++++++++++ frontend/package.json | 1 + frontend/src/hooks/useErrorHandler.ts | 6 ++++- frontend/src/main.tsx | 5 +++- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d22ca467..b3aba5b8 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -32,6 +32,7 @@ "color": "^4.2.3", "lib0": "^0.2.88", "moment": "^2.30.1", + "notistack": "^2.0.8", "randomcolor": "^0.6.2", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0", @@ -5312,6 +5313,42 @@ "resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz", "integrity": "sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==" }, + "node_modules/notistack": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/notistack/-/notistack-2.0.8.tgz", + "integrity": "sha512-/IY14wkFp5qjPgKNvAdfL5Jp6q90+MjgKTPh4c81r/lW70KeuX6b9pE/4f8L4FG31cNudbN9siiFS5ql1aSLRw==", + "dependencies": { + "clsx": "^1.1.0", + "hoist-non-react-statics": "^3.3.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/notistack" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "@mui/material": "^5.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/notistack/node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 77a48e7a..9330e10e 100755 --- a/frontend/package.json +++ b/frontend/package.json @@ -36,6 +36,7 @@ "color": "^4.2.3", "lib0": "^0.2.88", "moment": "^2.30.1", + "notistack": "^2.0.8", "randomcolor": "^0.6.2", "react": "^17.0.0 || ^18.0.0", "react-dom": "^17.0.0 || ^18.0.0", diff --git a/frontend/src/hooks/useErrorHandler.ts b/frontend/src/hooks/useErrorHandler.ts index 74673694..1876ed6f 100644 --- a/frontend/src/hooks/useErrorHandler.ts +++ b/frontend/src/hooks/useErrorHandler.ts @@ -1,7 +1,11 @@ +import { useSnackbar } from "notistack"; import { useCallback } from "react"; export function useErrorHandler() { - const handleError = useCallback((error: Error) => {}, []); + const { enqueueSnackbar } = useSnackbar(); + const handleError = useCallback((error: Error) => { + enqueueSnackbar(error.message || "Something went wrong...", { variant: "error" }); + }, []); return handleError; } diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index f59de3d2..489fad22 100755 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -6,6 +6,7 @@ import { store } from "./store/store"; import { Provider } from "react-redux"; import { PersistGate } from "redux-persist/integration/react"; import { persistStore } from "redux-persist"; +import { SnackbarProvider } from "notistack"; const persistor = persistStore(store); @@ -13,7 +14,9 @@ ReactDOM.createRoot(document.getElementById("root")!).render( - + + + From 8ae3713a430d82c28a745c76eab7739eff12e168 Mon Sep 17 00:00:00 2001 From: devleejb Date: Tue, 23 Jan 2024 13:25:21 +0900 Subject: [PATCH 4/4] Fix lint --- frontend/src/App.tsx | 4 ++-- frontend/src/hooks/useErrorHandler.ts | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d1dc6daf..78aab66e 100755 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -6,7 +6,7 @@ import "./App.css"; import { Box, CssBaseline, ThemeProvider, createTheme, useMediaQuery } from "@mui/material"; import { useSelector } from "react-redux"; import { RouterProvider, createBrowserRouter } from "react-router-dom"; -import { useEffect, useMemo } from "react"; +import { useMemo } from "react"; import { selectConfig } from "./store/configSlice"; import axios from "axios"; import { routes } from "./routes"; @@ -47,7 +47,7 @@ function App() { }, }, }); - }, []); + }, [handleError]); return ( diff --git a/frontend/src/hooks/useErrorHandler.ts b/frontend/src/hooks/useErrorHandler.ts index 1876ed6f..eb6b553f 100644 --- a/frontend/src/hooks/useErrorHandler.ts +++ b/frontend/src/hooks/useErrorHandler.ts @@ -3,9 +3,12 @@ import { useCallback } from "react"; export function useErrorHandler() { const { enqueueSnackbar } = useSnackbar(); - const handleError = useCallback((error: Error) => { - enqueueSnackbar(error.message || "Something went wrong...", { variant: "error" }); - }, []); + const handleError = useCallback( + (error: Error) => { + enqueueSnackbar(error.message || "Something went wrong...", { variant: "error" }); + }, + [enqueueSnackbar] + ); return handleError; }