Remix 非常强调 URL 状态。
在很多 SPA 里,开发者习惯把筛选条件、分页、排序都塞进本地 state: 结果就是刷新丢失、分享困难、后退前进怪异、SSR 不自然。
在 Remix 里,一个非常正统的做法是:
能放进 URL 的状态,就优先放进 URL。
比如筛选:
import { Form, useLoaderData } from "@remix-run/react";
import { json } from "@remix-run/node";
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const status = url.searchParams.get("status") ?? "all";
const ships = await listShips({ status });
return json({ ships, status });
}
export default function ShipsRoute() {
const { ships, status } = useLoaderData<typeof loader>();
return (
<>
<Form method="get">
<select name="status" defaultValue={status}>
<option value="all">全部</option>
<option value="arrived">已到港</option>
<option value="departed">已离港</option>
</select>
<button type="submit">筛选</button>
</Form>
<ul>
{ships.map((ship) => (
<li key={ship.id}>{ship.name}</li>
))}
</ul>
</>
);
}这时候:
- 刷新不丢
- 链接可分享
- 浏览器历史行为自然
- 服务端首屏也知道该查什么
这就是 Remix 很常说的一种迁移:
从“客户端状态优先”,转向“URL 和服务器状态优先”。