这一点非常关键,几乎是 Remix 使用熟练度的分水岭。
#用 <Form> 的场景
当这次提交会影响:
- 当前 URL
- 浏览器历史记录
- 页面级导航
- 提交成功后用户应该“到另一站”或“把这一站当成新状态”
比如:
- 登录
- 创建记录后跳详情页
- 搜索筛选并把条件放进 URL
- 编辑完成后返回详情页
#用 useFetcher() 的场景
当你只是想做一个“局部操作”,不想改主航线:
- 列表项点赞
- 切换收藏
- 表格里单行删除
- 弹窗内局部提交
- 自动补全建议
- 局部加载更多
示例:
import { useFetcher } from "@remix-run/react";
function FavoriteButton({ shipId, isFavorite }: { shipId: string; isFavorite: boolean }) {
const fetcher = useFetcher();
const optimisticFavorite =
fetcher.formData?.get("favorite") === "true" ? true :
fetcher.formData?.get("favorite") === "false" ? false :
isFavorite;
return (
<fetcher.Form method="post" action={`/ships/${shipId}/favorite`}>
<button
type="submit"
name="favorite"
value={optimisticFavorite ? "false" : "true"}
>
{optimisticFavorite ? "取消重点关注" : "设为重点关注"}
</button>
</fetcher.Form>
);
}这个交互的味道很像:
- 主船还停在当前泊位
- 旁边开一个快速作业通道
- 只处理这一个小货柜
- 不要整条航线改道
一句话记:
会不会换页面、改 URL、进历史栈?
会,优先 Form。
不会,优先 fetcher。