重新学习 React Router
前言
React Router 在推出 Remix 后变成了一个全栈框架,在 V7 版本之后,更是将 React Router 和 Remix 合并在一起,提供了一个全栈的解决方案。
常见问题
-
loader和clientLoader有什么区别?-
执行环境
loader: 在服务器端执行clientLoader: 在客户端(浏览器)执行
-
运行时机
loader: 在页面初始加载和每次导航时在服务器上运行clientLoader: 在客户端导航时运行,首次页面加载时不执行
-
数据获取能力
loader: 可以访问服务器资源(数据库、文件系统、内部API等)clientLoader: 只能访问浏览器可用的资源(如公共API、localStorage等)
-
安全性
loader: 可以包含敏感逻辑和凭证,因为代码不会发送到客户端clientLoader: 所有代码会发送到浏览器,不应包含敏感信息
-
用途场景
loader: 适用于需要服务器权限或敏感数据的操作clientLoader: 适用于提升客户端导航体验,减轻服务器负担的场景
这两个函数通常可以配合使用:
loader用于初始数据加载和服务器相关操作,clientLoader用于优化后续的客户端导航体验。loader将在你首次打开页面就是这个路由时执行,clientLoader将在你由其他路由导航到这个路由时执行。clientLoader在首次页面加载时不会执行。在clientLoader中,你可以使用serverLoader调用loaderimport type { Route } from "./+types/product"
// route("products/:pid", "./product.tsx");
import { fakeDb } from "../db"
export async function loader({ params }: Route.LoaderArgs) {
return fakeDb.getProduct(params.pid)
}
export async function clientLoader({ serverLoader, params }: Route.ClientLoaderArgs) {
const res = await fetch(`/api/products/${params.pid}`)
const serverData = await serverLoader()
return { ...serverData, ...res.json() }
}
export default function Product({ loaderData }: Route.ComponentProps) {
const { name, description } = loaderData
return (
<div>
<h1>{name}</h1>
<p>{description}</p>
</div>
)
} -