remix
remix copied to clipboard
MetaFunction doesn't take loader throwing errors/responses into account for data type
What version of Remix are you using?
1.7.4
Steps to Reproduce
- export a
loaderthat conditionally throws an error or a response, but otherwise returns a JSON response - export a
metafunction which is accessing adataproperty, useMetaFunctionto obtaindatatype - create an
ErrorBoundaryorCatchBoundary, depending on step 1 - satisfy the condition that causes
loaderto throw
This is my slightly contrived app/routes/item.$num.tsx, which ensures that the $num param is a valid number, otherwise throws an error:
import type { LoaderArgs, MetaFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import invariant from "tiny-invariant";
export async function loader({ params }: LoaderArgs) {
invariant(params.num, "num is required");
const num = Number(params.num);
invariant(!Number.isNaN(num), "num is not a number");
return json({ num })
}
export const meta: MetaFunction<typeof loader> = ({ data }) => {
return {
title: `Item ${data.num}`,
}
}
export default function Item() {
const { num } = useLoaderData<typeof loader>()
return (
<h1>Item {num}</h1>
)
}
export function ErrorBoundary({ error }: { error: Error }) {
return (
<div>
<h1>Something went wrong</h1>
<pre>{error.message}</pre>
</div>
)
}
Expected Behavior
I expected the data type in the meta function to stop me from unconditionally accessing data.num, assuming that data will always be an object.
Actual Behavior
The types in the meta function act like data will always be the object serialized from the loader, but in case the loader throws by accessing the root with an invalid $num, for example /item/foo, it will be undefined, so accessing data.num will throw an error.