Remix框架指南
Loader(数据获取)
// app/routes/users.$id.tsx
import { json } from '@remix-run/node';
import { useLoaderData } from '@remix-run/react';
import type { LoaderFunctionArgs } from '@remix-run/node';
export async function loader({ params }: LoaderFunctionArgs) {
const user = await getUser(params.id);
if (!user) throw new Response('Not Found', { status: 404 });
return json({ user });
}
export default function UserPage() {
const { user } = useLoaderData<typeof loader>();
return <h1>{user.name}</h1>;
}
Action(表单处理)
import { Form, useActionData } from '@remix-run/react';
import { redirect } from '@remix-run/node';
import type { ActionFunctionArgs } from '@remix-run/node';
export async function action({ request }: ActionFunctionArgs) {
const formData = await request.formData();
const name = formData.get('name') as string;
if (!name) return json({ error: 'Name required' }, { status: 400 });
await createUser({ name });
return redirect('/users');
}
export default function NewUser() {
const data = useActionData<typeof action>();
return (
<Form method="post">
<input name="name" type="text" />
{data?.error && <p>{data.error}</p>}
<button type="submit">Create</button>
</Form>
);
}
文件路由
app/routes/
├── _index.tsx # /
├── about.tsx # /about
├── users._index.tsx # /users
├── users.$id.tsx # /users/:id
├── users.$id.edit.tsx # /users/:id/edit
└── _layout.tsx # 共享布局
错误边界
export function ErrorBoundary() {
const error = useRouteError();
if (isRouteErrorResponse(error)) {
return <div>{error.status} {error.statusText}</div>;
}
return <div>Something went wrong</div>;
}