diff --git a/app/errors.js b/app/errors.js new file mode 100644 index 0000000..eab7271 --- /dev/null +++ b/app/errors.js @@ -0,0 +1,53 @@ +// https://remix.run/docs/en/main/route/error-boundary-v2 +// useRouteError: 4xx/5xx (catch all errors) +// isRouteErrorResponse: 4xx (client errors for fine-tuning the UI) +// +// example (throw error): +// throw new Response("authentication failed", { status: 401, statusText: "Unauthorized" }); +import { isRouteErrorResponse, useRouteError } from "@remix-run/react"; + +function useErrorHandler() { + const error = useRouteError(); + + if (isRouteErrorResponse(error)) { + /* + Example: + + error: ErrorResponse { + status: 400, + statusText: 'Bad Request', + internal: false, + data: 'custom message' + } + */ + return { + status: error.status, + statusText: error.statusText, + data: error.data, + }; + } + + if (error instanceof Error) { + /* + Example: + ReferenceError: ... + + Important: + - message + - stack + */ + return { + status: error.status, + statusText: error.statusText, + data: error.data, + message: error.message, + stack: error.stack, + }; + } + + return { + statusText: "Unknown Error", + }; +} + +export default useErrorHandler; diff --git a/app/root.jsx b/app/root.jsx index 1446ba8..8c9bc47 100644 --- a/app/root.jsx +++ b/app/root.jsx @@ -7,6 +7,8 @@ import { ScrollRestoration, } from "@remix-run/react"; +import useErrorHandler from "./errors"; + import styles from "bootstrap/dist/css/bootstrap.min.css"; export const links = () => [ @@ -34,3 +36,28 @@ export default function App() { ); } + +// https://remix.run/docs/en/main/guides/errors +// https://remix.run/docs/en/main/route/error-boundary-v2 +export function ErrorBoundary() { + // status, statusText, data, message, stack + const { statusText } = useErrorHandler(); + + return ( + + + + + {statusText} + + + + + + + + + + + ); +} diff --git a/app/routes/_index.jsx b/app/routes/_index.jsx index 3a4f61d..211a8b8 100644 --- a/app/routes/_index.jsx +++ b/app/routes/_index.jsx @@ -1,5 +1,7 @@ import { Link } from "@remix-run/react"; +import useErrorHandler from "~/errors"; + import styles from "~/styles/_index.css"; export const links = () => [{ rel: "stylesheet", href: styles }]; @@ -61,3 +63,37 @@ export default function Index() { ); } + +export function ErrorBoundary() { + const { status, statusText, data, message, stack } = useErrorHandler(); + + if (status === 401) { + return ( +
+
+
+
+

You must be logged in.

+
+
+
+
+ ); + } + + return ( +
+
+
+
+ Something unexpected went wrong. Sorry about that. + {statusText &&

{statusText}

} + {data &&

{data}

} + {message &&

{message}

} + {stack &&
{stack}
} +
+
+
+
+ ); +}