Skip to content

Commit

Permalink
refactor(catch-boundary): Switch to V2 + Vite (#511)
Browse files Browse the repository at this point in the history
  • Loading branch information
machour committed Jun 16, 2024
1 parent 86c9a39 commit f0b8d0a
Show file tree
Hide file tree
Showing 19 changed files with 248 additions and 151 deletions.
4 changes: 0 additions & 4 deletions catch-boundary/.eslintrc.js

This file was deleted.

64 changes: 0 additions & 64 deletions catch-boundary/app/routes/users.$userId.tsx

This file was deleted.

29 changes: 0 additions & 29 deletions catch-boundary/package.json

This file was deleted.

11 changes: 0 additions & 11 deletions catch-boundary/remix.config.js

This file was deleted.

2 changes: 0 additions & 2 deletions catch-boundary/remix.env.d.ts

This file was deleted.

22 changes: 0 additions & 22 deletions catch-boundary/tsconfig.json

This file was deleted.

84 changes: 84 additions & 0 deletions error-boundary/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/**
* This is intended to be a basic starting point for linting in your app.
* It relies on recommended configs out of the box for simplicity, but you can
* and should modify this configuration to best suit your team's needs.
*/

/** @type {import('eslint').Linter.Config} */
module.exports = {
root: true,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
env: {
browser: true,
commonjs: true,
es6: true,
},
ignorePatterns: ["!**/.server", "!**/.client"],

// Base config
extends: ["eslint:recommended"],

overrides: [
// React
{
files: ["**/*.{js,jsx,ts,tsx}"],
plugins: ["react", "jsx-a11y"],
extends: [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"plugin:jsx-a11y/recommended",
],
settings: {
react: {
version: "detect",
},
formComponents: ["Form"],
linkComponents: [
{ name: "Link", linkAttribute: "to" },
{ name: "NavLink", linkAttribute: "to" },
],
"import/resolver": {
typescript: {},
},
},
},

// Typescript
{
files: ["**/*.{ts,tsx}"],
plugins: ["@typescript-eslint", "import"],
parser: "@typescript-eslint/parser",
settings: {
"import/internal-regex": "^~/",
"import/resolver": {
node: {
extensions: [".ts", ".tsx"],
},
typescript: {
alwaysTryTypes: true,
},
},
},
extends: [
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
],
},

// Node
{
files: [".eslintrc.cjs"],
env: {
node: true,
},
},
],
};
1 change: 0 additions & 1 deletion catch-boundary/.gitignore → error-boundary/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ node_modules

/.cache
/build
/public/build
.env
12 changes: 6 additions & 6 deletions catch-boundary/README.md → error-boundary/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
# CatchBoundary Example
# ErrorBoundary Example

If you want to handle _expected_ errors, you use a `CatchBoundary` to catch those types of errors. Think about HTTP-400-level errors like unauthorized etc.
If you want to handle errors, export an `ErrorBoundary` from your route.

## Preview

Open this example on [CodeSandbox](https://codesandbox.com):

[![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/remix-run/examples/tree/main/catch-boundary)
[![Open in CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/remix-run/examples/tree/main/error-boundary)

## Example

In this example, we have a list of users and one user that does not exist. When you navigate to the user that does not exist, our CatchBoundary renders in place of the component for that route.
In this example, we have a list of users and one user that does not exist. When you navigate to the user that does not exist, our ErrorBoundary renders in place of the component for that route.

Check [app/routes/users/$userId.tsx](app/routes/users/$userId.tsx) to see the CatchBoundary in action.
Check [app/routes/users/$userId.tsx](app/routes/users/$userId.tsx) to see the ErrorBoundary in action.

## Related Links

- [CatchBoundary in the Remix Docs](https://remix.run/route/catch-boundary)
- [ErrorBoundary in the Remix Docs](https://remix.run/route/error-boundary)
File renamed without changes.
19 changes: 8 additions & 11 deletions catch-boundary/app/root.tsx → error-boundary/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
import type { MetaFunction } from "@remix-run/node";
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";

export const meta: MetaFunction = () => ({
charset: "utf-8",
title: "New Remix App",
viewport: "width=device-width,initial-scale=1",
});

export default function App() {
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Outlet />
{children}
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}

export default function App() {
return <Outlet />;
}
File renamed without changes.
61 changes: 61 additions & 0 deletions error-boundary/app/routes/users.$userId.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { LoaderFunctionArgs, MetaFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
import {
isRouteErrorResponse,
useLoaderData,
useParams,
useRouteError,
} from "@remix-run/react";

import { getUsers } from "~/data.server";

export const meta: MetaFunction<typeof loader> = ({ data }) => {
// Handle our 404 gracefully by setting a generic error as page title
if (!data || !data.user) {
return [{ title: "User not found!" }];
}
return [{ title: data.user.name }];
};

export const loader = async ({ params }: LoaderFunctionArgs) => {
const userId = params.userId;

const users = getUsers();
const user = users.find(({ id }) => id === userId);

if (!user) {
// When there's an expected error (like no found user) throw a response.
throw new Response("Not Found", { status: 404 });
}

return json({ user });
};

export default function User() {
const { user } = useLoaderData<typeof loader>();
return <div>Hi there {user.name}!</div>;
}

// Export an ErrorBoundary and use the useRouteError/isRouteErrorResponse
// combo to handle thrown responses like the 404 we have in our loader.
// You can also catch thrown responses from actions as well.
export function ErrorBoundary() {
const error = useRouteError();
const params = useParams();

if (isRouteErrorResponse(error) && error.status === 404) {
return (
<span style={{ color: "red" }}>
User with ID "{params.userId}" not found!
</span>
);
}

console.error(error);

return (
<div>
<pre>{JSON.stringify(error, null, 2)}</pre>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Link, Outlet, useLoaderData } from "@remix-run/react";
import { getUsers } from "~/data.server";

export const meta: MetaFunction = () => {
return { title: "Users" };
return [{ title: "Users" }];
};

export const loader = async () => {
Expand Down
Loading

0 comments on commit f0b8d0a

Please sign in to comment.