Open8
【Remix】ネストしたloaderのnot foundをroot.tsxのError Boundaryでキャッチしたい。
Remixのloaderで投げた404エラーを、root.tsxに設定したerror boundaryがキャッチしてくれないので原因を調べる。
"@remix-run/node": "^2.14.0",
"@remix-run/react": "^2.14.0",
"@remix-run/serve": "^2.14.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
やりたいこと。
/hoge/{id}
をブラウザにアクセスしたときに、存在しないIDの場合root.tsxのエラーバウンダリーにキャッチさせたい。
キャッチせずにブラウザのNot Foundが出るのを防ぎたい感じです。
構成とコード
app
├── app.css
├── data.ts
├── root.tsx
└── routes
├── contacts.$contactId.tsx
└── contacts.tsx
root.tsx
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
isRouteErrorResponse,
useRouteError,
} from "@remix-run/react";
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
export default function App() {
return <Outlet />;
}
export function ErrorBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error)) {
return (
<div>
<h1>
{error.status} {error.statusText}
</h1>
<p>{error.data}</p>
</div>
);
} else if (error instanceof Error) {
return (
<div>
<h1>Error</h1>
<p>{error.message}</p>
<p>The stack trace is:</p>
<pre>{error.stack}</pre>
</div>
);
} else {
return <h1>Unknown Error</h1>;
}
}
contacts.$contactId.tsx
export const loader = async () => {
throw new Response(null, { status: 404, statusText: "Not Found" });
}
/contacts/123
同ファイル内にError Boundaryを設置してみる。
contacts.$contactId.tsx
+import { isRouteErrorResponse, useRouteError } from "@remix-run/react";
export const loader = async () => {
throw new Response(null, { status: 404, statusText: "Not Found" });
}
+export function ErrorBoundary() {
+ const error = useRouteError();
+ if (isRouteErrorResponse(error)) {
+ return (
+ <div>
+ <h1>
+ {error.status} {error.statusText}
+ </h1>
+ <p>{error.data}</p>
+ </div>
+ );
+ } else if (error instanceof Error) {
+ return (
+ <div>
+ <h1>Error</h1>
+ <p>{error.message}</p>
+ <p>The stack trace is:</p>
+ <pre>{error.stack}</pre>
+ </div>
+ );
+ } else {
+ return <h1>Unknown Error</h1>;
+ }
+}
ブラウザには/contacts
の内容が表示されて、こんなエラーがコンソールに出た。
Matched leaf route at location "/contacts/123" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an
"empty" page.
element or Component
がないよって。って言ってるので、
contacts.contactId.tsx
export const loader = async () => {
throw new Response(null, { status: 404, statusText: "Not Found" });
}
+export default function Page() {
+ return <h1>test</h1>
+}
// ここに記述していたerror boundaryは削除
キャッチしてくれた。
remix.run/docs/ja/main/guides/errors#error-handling
Remix will automatically catch errors and render the nearest error boundary for errors thrown while:
- rendering in the browser
- rendering on the server
- in a loader during the initial server-rendered document request
- in an action during the initial server-rendered document request
- in a loader during a client-side transition in the browser (Remix serializes the error and sends it over
- the network to the browser)
- in an action during a client-side transition in the browser
in a loader during the initial server-rendered document request
レンダーが走らないとrootのエラーバウンダリーで処理されない?
直接解決するわけではないけど、
api.contacts.$contactId.tsx
っていうファイル名にして、apiだよってわかるようにするか〜。
わざわざ/api/contacts/{id}
って打つ必要があるので、あまり打たれないかな。
Thanks💪
remixでAPIだけ生やしたいときの実装はきついのかな。
ソース読んで勉強します。わかったらまたここに投稿する。