Skip to content

Commit

Permalink
feat!: remove CatchBoundary logic (#5781)
Browse files Browse the repository at this point in the history
Co-authored-by: Michaël De Boey <info@michaeldeboey.be>
  • Loading branch information
brophdawg11 and MichaelDeBoey committed Jul 10, 2023
1 parent 1f5f8af commit 7dcc14b
Show file tree
Hide file tree
Showing 55 changed files with 236 additions and 2,505 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
1 change: 0 additions & 1 deletion docs/pages/api-development-strategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ The lifecycle is thus either:
| Flag | Description |
| ------------------------ | --------------------------------------------------------------------- |
| `v2_dev` | Enable the new development server (including HMR/HDR support) |
| `v2_errorBoundary` | Combine `ErrorBoundary`/`CatchBoundary` into a single `ErrorBoundary` |
| `v2_headers` | Leverage ancestor `headers` if children do not export `headers` |
| `v2_normalizeFormMethod` | Normalize `useNavigation().formMethod` to be an uppercase HTTP Method |
| `v2_routeConvention` | Enable the flat routes style of file-based routing |
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
36 changes: 0 additions & 36 deletions docs/route/catch-boundary.md

This file was deleted.

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

This file was deleted.

56 changes: 41 additions & 15 deletions docs/route/error-boundary.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,56 @@
---
title: ErrorBoundary
new: true
---

# `ErrorBoundary`

<docs-warning>The behaviors of `CatchBoundary` and `ErrorBoundary` are changing in v2. You can prepare for this change at your convenience with the `v2_errorBoundary` future flag. For instructions on making this change see the [v2 guide][v2guide].</docs-warning>
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.

An `ErrorBoundary` is a React component that renders whenever there is an error anywhere on the route, either during rendering or during data loading. We use the word "error" to mean an uncaught exception; something you didn't anticipate happening. You can intentionally throw a `Response` to render the `CatchBoundary`, but everything else that is thrown is handled by the `ErrorBoundary`.
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,
useRouteError,
} from "@remix-run/react";

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>;
}
}
```

[error-boundaries]: https://reactjs.org/docs/error-boundaries.html
[error-boundary-v2]: ./error-boundary-v2
[v2guide]: ../pages/v2#catchboundary-and-errorboundary
[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
24 changes: 24 additions & 0 deletions docs/utils/is-route-error-response.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,28 @@ toc: false

<docs-info>This util is simply a re-export of [React Router's `isRouteErrorResponse`][rr-isrouteerrorresponse].</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()`)

```tsx
import { json } from "@remix-run/node"; // or cloudflare/deno

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-isrouteerrorresponse]: https://reactrouter.com/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 @@ -20,7 +20,6 @@ test.describe("actions", () => {
config: {
future: {
v2_routeConvention: true,
v2_errorBoundary: true,
v2_normalizeFormMethod: true,
},
},
Expand Down
Loading

0 comments on commit 7dcc14b

Please sign in to comment.