React Router 如何编写 Resource Route 让路由直接返回 PDF、JSON 等响应而非组件?
发布时间:2026/9/9 13:49:44 作者:尧图编辑部 阅读量:1,286

React Router 如何编写 Resource Route 让路由直接返回 PDF、JSON 等响应而非组件【免费下载链接】react-routerDeclarative routing for React项目地址: https://gitcode.com/GitHub_Trending/re/react-router如果你需要在 React Router 应用中让某个 URL 直接返回 PDF 文件、JSON 数据、图片甚至 webhook 响应而不是渲染一段界面官方文档把这个能力叫做Resource Routes服务端渲染时路由可以提供资源而不是组件见 docs/how-to/resource-routes.md。Resource Routes 适用于framework 模式和 data 模式文档标注[MODES: framework, data]。完成本场景的目标是让一个路由不导出组件由loader/action直接生成Response并在应用的其他页面正确链接到它。让路由变成 Resource Route不导出组件即可路由按约定成为 resource route 的条件只有一个它的模块导出loader或action但不导出 default 组件docs/how-to/resource-routes.md。以返回 PDF 报告为例先在路由配置中注册路由route(/reports/pdf/:id, pdf-report.ts);然后编写路由模块注意没有 default export这就是它成为 resource route 的关键import type { Route } from ./types/pdf-report; export async function loader({ params }: Route.LoaderArgs) { const report await getReport(params.id); const pdf await generateReportPDF(report); return new Response(pdf, { status: 200, headers: { Content-Type: application/pdf, }, }); }getReport和generateReportPDF是你自己业务代码中的函数Content-Type: application/pdf声明了响应体是 PDF。换成 JSON 响应时同理返回Response并带上对应的Content-Type即可。从页面链接到 Resource Route必须用整页导航resource route 不返回组件所以不能用 React Router 的客户端路由去访问它。链接到 resource route 时必须使用a标签或带reloadDocument属性的Link否则 React Router 会尝试走客户端路由此时你会收到一条有用的错误提示文档原话youll get a helpful error message if you make this mistake。Link reloadDocument to/reports/pdf/123 View as PDF /LinkreloadDocument的含义见 docs/api/components/Link.md点击时不走客户端路由浏览器像处理普通a href一样完成整页导航。处理不同的 HTTP 方法同一个 resource route 可以用loader和action分别响应不同方法docs/how-to/resource-routes.mdGET请求由loader处理POST、PUT、PATCH、DELETE由action处理。import type { Route } from ./types/resource; export function loader(_: Route.LoaderArgs) { return Response.json({ message: I handle GET }); } export function action(_: Route.ActionArgs) { return Response.json({ message: I handle everything else, }); }上面这段代码同时也是文档给出的 JSON 响应示例Response.json直接生成带 JSON 编码的响应。返回类型怎么选Response 还是 data()Resource route 对返回类型是灵活的可以返回Response实例也可以返回data()对象。文档给出的判断标准是面向外部消费的 resource route返回Response实例——响应编码在代码里是显式的不用去猜 React Router 内部如何把data()转换成Response从fetcher或Form提交访问的 resource route返回data()——与 UI 路由的 loader/action 保持一致并允许通过data()/Await把 promise 流式传送到 UI。data()的签名是function dataD(data: D, init?: number | ResponseInit)用于在不强制序列化为真正Response的情况下携带headers/statusdocs/api/utils/data.mdimport { data } from react-router; export async function action({ request }: Route.ActionArgs) { let formData await request.formData(); let item await createItem(formData); return data(item, { headers: { X-Custom-Header: value }, status: 201, }); }错误处理什么时候触发 handleError什么时候不触发这一节直接决定你的 resource route 出错时客户端和服务器各自看到什么docs/how-to/resource-routes.md抛出Error或Response/data()以外的任何东西会触发handleError并产生 500 HTTP 响应export function action() { let db await getDb(); if (!db) { // Fatal error - return a 500 response and trigger handleError throw new Error(Could not connect to DB); } // ... }handleError是在entry.server.tsx中导出的可选函数用于接管服务端错误的日志记录与上报默认行为是打到 console。只要 resource route 生成了一个Response通过new Response()或data()就视为执行成功不会触发handleError——因为 API 已经为 HTTP 请求产出了 Response。这对 thrown response 和带 4xx/5xx 状态码的 returned response 同样成立。文档说明这个行为与fetch()一致fetch()收到 4xx/5xx 响应时也不会返回 rejected promise。export function action() { // Non-fatal error - dont trigger handleError: throw new Response( { error: Unauthorized }, { status: 401 }, ); }文档还指出throw new Response(...)、return new Response(...)、throw data(...)、return data(...)这几种写法在上述 401 示例中等价。Error Boundary 只在 resource route 从 UI 访问时才相关当它被fetcher调用或Form提交访问时throw会冒泡到最近的 UIErrorBoundary。直接通过浏览器整页导航访问时不涉及 Error Boundary。验证与限制按上面的路径做完后可以用文档给出的行为本身作为核对依据用 GET 请求访问该路由应命中loader用 POST/PUT/PATCH/DELETE 请求应命中action——两个方法各返回不同的 JSON 时即可确认分派正确在页面中点击指向 resource route 的普通Link不带reloadDocument应得到文档所说的 helpful error message换成a或Link reloadDocument后走整页导航resource route 中throw new Error(...)时应得到 500 响应并触发handleErrorthrow/return401Response时客户端直接收到 401且不触发handleError。限制方面注意两点前提Resource Routes 只在服务端渲染framework/data 模式场景下按上述约定生效如果模块不小心导出了 default 组件它就不再是 resource route上述无 default export 即资源路由的约定不再成立。想进一步控制响应细节可继续查阅 entry.server.tsx 中的handleError自定义错误处理与handleDataRequest修改 data request 响应两个可选导出链接行为见 Link 的reloadDocument参数说明。【免费下载链接】react-routerDeclarative routing for React项目地址: https://gitcode.com/GitHub_Trending/re/react-router创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考