Repository navigation
throw or return Error Response from loaders? #14822
Replies: 2 comments
|
Throwing doesn't affect the return type of the function in TS, so the type of |
|
Short version: for a 404 (or any "stop rendering and show an error UI" case) you want to Why throwing is correct for the 404 case: Throwing short-circuits the render. When a loader throws, React Router stops rendering that route's component and renders the nearest The canonical pattern uses import { data } from "react-router";
export async function loader({ params }: Route.LoaderArgs) {
const record = await db.getRecord(params.id);
if (!record) {
throw data("Record Not Found", { status: 404 });
}
return record; // <- if you reach here, `record` is guaranteed defined
}import { isRouteErrorResponse, useRouteError } from "react-router";
export function ErrorBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error) && error.status === 404) {
return <h1>Not found</h1>;
}
throw error; // let it bubble to a parent boundary
}If you return the 404 Response instead, you don't get this behavior — for a route with a component, the return value becomes your There's also a TypeScript benefit for the 404 / For redirects specifically: import { redirect } from "react-router";
if (!isLoggedIn(request)) throw redirect("/login");The docs show On your testing pain — this is the legitimate downside, and the fix is to test for the throw rather than restructure your app around return values. A thrown import { isRouteErrorResponse } from "react-router";
it("404s for missing records", async () => {
try {
await loader({ params: { id: "nope" } } as any);
throw new Error("expected loader to throw");
} catch (thrown) {
// thrown is a Response
expect(isRouteErrorResponse(thrown) || thrown instanceof Response).toBe(true);
expect((thrown as Response).status).toBe(404);
}
});
Docs for reference:
|
Uh oh!
There was an error while loading. Please reload this page.
Hi,
I'm currently working on an app with react-router v7 as a framework.
So far, my loaders check the validity of certain routes, and throw a 404 Response if the route makes no sense, or return a redirect.
I've done this because I've seen examples with throwing.
I have not found anything about this in the docs (maybe it should be added there)
I'm wondering whether throwing the 404 response is a good practice, or if it should just be returned.
I've tried both quickly and have not seen a difference on the user end
There is a difference in testing complexity, which would be much simpler if i simply returned responses instead of throwing, which I'm struggling with now, trying to test a complex loader.
All reactions