MetaFunction doesn't take loader throwing errors/responses into account for data type #4451
Closed
Description
What version of Remix are you using?
1.7.4
Steps to Reproduce
- export a
loader
that conditionally throws an error or a response, but otherwise returns a JSON response - export a
meta
function which is accessing adata
property, useMetaFunction
to obtaindata
type - create an
ErrorBoundary
orCatchBoundary
, depending on step 1 - satisfy the condition that causes
loader
to 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.