Skip to content

Commit

Permalink
Remove CatchBoundary for v2 (#5781)
Browse files Browse the repository at this point in the history
  • Loading branch information
brophdawg11 authored Mar 17, 2023
1 parent 9506d4e commit b8e5eaa
Show file tree
Hide file tree
Showing 39 changed files with 405 additions and 2,508 deletions.
6 changes: 6 additions & 0 deletions .changeset/eight-squids-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@remix-run/react": major
"@remix-run/server-runtime": major
---

Remove `v2_errorBoundary` flag and `CatchBoundary` logic
5 changes: 0 additions & 5 deletions docs/api/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,6 @@ title: Conventions

[Moved →][moved-41]

### CatchBoundary

[Moved →][moved-42]

### ErrorBoundary

[Moved →][moved-43]
Expand Down Expand Up @@ -239,7 +235,6 @@ title: Conventions
[moved-39]: ../route/links
[moved-40]: ../route/links#htmllinkdescriptor
[moved-41]: ../route/links#pagelinkdescriptor
[moved-42]: ../route/catch-boundary
[moved-43]: ../route/error-boundary
[moved-44]: ../route/handle
[moved-45]: ../route/should-revalidate
Expand Down
2 changes: 1 addition & 1 deletion docs/guides/routing.md
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ export async function loader({ params }: LoaderArgs) {

You can add splats at any level of your route hierarchy. Any sibling routes will match first (like `/files/mine`).

It's common to add a `routes/$.jsx` file build custom 404 pages with data from a loader (without it, Remix renders your root `CatchBoundary` with no ability to load data for the page when the URL doesn't match any routes).
It's common to add a `routes/$.jsx` file build custom 404 pages with data from a loader (without it, Remix renders your root `ErrorBoundary` with no ability to load data for the page when the URL doesn't match any routes).

## Conclusion

Expand Down
7 changes: 0 additions & 7 deletions docs/pages/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,4 @@ Again, `formData.getAll()` is often all you need, we encourage you to give it a
[form-data]: https://developer.mozilla.org/en-US/docs/Web/API/FormData
[query-string]: https://www.npmjs.com/package/query-string
[ramda]: https://www.npmjs.com/package/ramda

## What's the difference between `CatchBoundary` & `ErrorBoundary`?

Error boundaries render when your application throws an error and you had no clue it was going to happen. Most apps just go blank or have spinners spin forever. In remix the error boundary renders and you have granular control over it.

Catch boundaries render when you decide in a loader that you can't proceed down the happy path to render the UI you want (auth required, record not found, etc.), so you throw a response and let some catch boundary up the tree handle it.

[watch-on-you-tube]: https://www.youtube.com/watch?v=w2i-9cYxSdc&ab_channel=Remix
35 changes: 0 additions & 35 deletions docs/route/catch-boundary.md

This file was deleted.

11 changes: 0 additions & 11 deletions docs/route/error-boundary-v2.md

This file was deleted.

54 changes: 39 additions & 15 deletions docs/route/error-boundary.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,52 @@ title: ErrorBoundary

# `ErrorBoundary`

<docs-warning>The separation of `CatchBoundary` and `ErrorBoundary` has been deprecated and Remix v2 will use a singular `ErrorBoundary` for all thrown Responses and Errors. It is recommended that you opt-into the new behavior in Remix v1 via the `future.v2_errorBoundary` flag in your `remix.config.js` file. Please refer to the [ErrorBoundary (v2)][error-boundary-v2] docs for more information.</docs-warning>
<docs-info>The Remix `ErrorBoundary` is an implementation of the React Router [`errorElement`/`ErrorBoundary`][rr-error-boundary].</docs-info>

An `ErrorBoundary` is a React component that renders whenever there is an error anywhere on the route, either during rendering or during data loading.
A Remix `ErrorBoundary` component works just like normal React [error boundaries][error-boundaries], but with a few extra capabilities. When there is an error in your route component, the `ErrorBoundary` will be rendered in its place, nested inside any parent routes. `ErrorBoundary` components also render when there is an error in the `loader` or `action` functions for a route, so all errors for that route may be handled in one spot.

**Note:** We use the word "error" to mean an uncaught exception; something you didn't anticipate happening. This is different from other types of "errors" that you are able to recover from easily, for example a 404 error where you can still show something in the user interface to indicate you weren't able to find some data.
The most common use-cases tend to be:

A Remix `ErrorBoundary` component works just like normal React [error boundaries][error-boundaries], but with a few extra capabilities. When there is an error in your route component, the `ErrorBoundary` will be rendered in its place, nested inside any parent routes. `ErrorBoundary` components also render when there is an error in the `loader` or `action` functions for a route, so all errors for that route may be handled in one spot.
- You may intentionally throw a 4xx `Response` to trigger an error UI
- Throwing a 400 on bad user input
- Throwing a 401 for unauthorized access
- Throwing a 404 when you can't find requested data
- React may unintentionally throw an `Error` if it encounters a runtime error during rendering

An `ErrorBoundary` component receives one prop: the `error` that occurred.
To obtain the thrown object, you can use the [`useRouteError`][use-route-error] hook. When a `Response` is thrown, it will be automatically unwrapped into an `ErrorResponse` instance with `state`/`statusText`/`data` fields so that you don't need to bother with `await response.json()` in your component. To differentiate thrown `Response`'s from thrown `Error`'s' you can use the [`isRouteErrorResponse`][is-route-error-response] utility.

```tsx
export function ErrorBoundary({ error }) {
return (
<div>
<h1>Error</h1>
<p>{error.message}</p>
<p>The stack trace is:</p>
<pre>{error.stack}</pre>
</div>
);
import { isRouteErrorResponse } from "@remix-run/node";
import { useRouteError } from "@remix-run/react";

export function ErrorBoundary() {
let 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>;
}
}
```

[error-boundaries]: https://reactjs.org/docs/error-boundaries.html
[error-boundary-v2]: ./error-boundary-v2
[rr-error-boundary]: https://reactrouter.com/en/main/route/error-element
[use-route-error]: ../hooks/use-route-error
[is-route-error-response]: ../utils/is-route-error-response.md
33 changes: 33 additions & 0 deletions docs/utils/is-route-error-response.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: isRouteErrorResponse
---

# `isRouteErrorResponse`

<docs-info>This is just a re-export of the React Router [`isRouteErrorResponse`][rr-is-route-error-response] utility.</docs-info>

When a response is thrown from an action or loader, it will be unwrapped into an `ErrorResponse` so that your component doesn't have to deal with the complexity of unwrapping it (which would require React state and effects to deal with the promise returned from `res.json()`)

```jsx
import { json } from "@remix-run/node";

export function action() {
throw json(
{ message: "email is required" },
{ status: 400, statusText: "Bad Request" }
);
}

export function ErrorBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error)) {
error.status; // 400
error.statusText; // Bad Request
error.data; // { "message: "email is required" }
}
}
```

<docs-info>If the user visits a route that does not match any routes in the app, Remix itself will throw a 404 response.</docs-info>

[rr-is-route-error-response]: https://reactrouter.com/en/main/utils/is-route-error-response
1 change: 0 additions & 1 deletion integration/action-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ test.describe("actions", () => {
fixture = await createFixture({
future: {
v2_routeConvention: true,
v2_errorBoundary: true,
},
files: {
"app/routes/urlencoded.jsx": js`
Expand Down
Loading

0 comments on commit b8e5eaa

Please sign in to comment.