Remix loader 函数是一个获取当前页面页面数据的函数,常常与 useLoaderData 一同合作运用
当前 Remix 版别:1.15.0
主要内容
- 界说方法
- loader 与 useLoaderData 运用
- 回来值类型以及运用方法
- 参数/上下文
- 重定向
- 过错处理
- laoder 操作纯 api 输出数据运用
loader 函数界说
- Remix Route 中界说 loader 函数
- export 对外暴露
- 回来 json/defer/ new Response 实例等
常常与 ORM/ODM 进行交互,从数据库获取数据。
loader 函数合作 useLoaderData 一同运用
import { json } from "@remix-run/node"; // or cloudflare/deno
export const loader = async () => {
return json({ ok: true });
};
export default function Users() {
const data = useLoaderData();
return (
<>{JSON.stringly(data)}</>
);
}
loader 函数回来值
- json 一般是同步数据,json 函数能够指定两个参数,第一个是 方针数据,第二个是 http 状况
export const loader = () => {
json({jsonKey: "jsonValue"})
}
export const loader = () => {
json({jsonKey: "jsonValue"}, {
status: 200,
headers: {
"Cache-Control": "no-store"
}
})
}
- defer 允许回来一个 promise, 一般合作
Await 组件运用
json 数据一般是回来一个同步 json 目标,但是 defer 允许我们回来值能够是一个 promise
import { defer } from "@remix-run/node"; // or cloudflare/deno
export const loader = async () => {
const thePromise = loadSlowDataAsync(); // 发生一个 Promise 值
// So you can write this without awaiting the promise:
return defer({
critical: "data",
slowPromise: thePromise, // 直接将 Promise 的值交给 defer
});
};
值得注意的是 defer 回来的值不直接运用,需求合作Suspense
+Await
组件运用, 下面是一个 loader 回来 defer 的示例:
import { defer } from "@remix-run/node";
import { Await, useLoaderData } from "@remix-run/react";
import { Suspense } from "react";
export const loader = () => {
let p = new Promise((resolve) => {
setTimeout(() => {
resolve("defer a promise value");
}, 2000);
});
return defer({
pv: p,
});
};
export default function Defer() {
const data = useLoaderData();
console.log(data);
return (
<div>
<div>This is defer value: </div>
<Suspense fallback={<div>Loading...</div>}>
<Await resolve={data.pv}>{(data) => <div>{data}</div>}</Await>
</Suspense>
</div>
);
- new Response 一个规范的呼应示例
export async function loader() {
const body = JSON.stringify({ loader: "loader data"});
return new Response(body, {
headers: {
"Content-Type": "application/json",
},
});
}
export default function() {
return <div>loader.response</div>
}
Response 是 Fetch API 的呼应目标。
loader 函数的类型
loader 函数打通了其类型,在运用的是 typeof 执行 loader 函数合作 LoaderArgs 类型:
import type { LoaderArgs } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
export async function loader(args: LoaderArgs) {
return json({ name: "Ryan", date: new Date() });
}
export default function SomeRoute() {
const data = useLoaderData<typeof loader>();
}
loader 函数中获取 params
export async function loader({ params }: LoaderArgs) {
let id = params.id; // "123"
}
一般 id 用于供给给后端查询数据库
loader 函数中处理 headers
export async function loader({ request }: LoaderArgs) {
// read a cookie
const cookie = request.headers.get("Cookie");
// parse the search params for `?q=`
const url = new URL(request.url);
const query = url.searchParams.get("q");
}
从 request 目标运用 get 获取 “Cookie” headers 然后运用 request.url 获取 searchParams 这些常用的 url 数据。
loader 函数上下文
假如你有一些上下文,需求串能够修改 server.js 中的内容,这儿以 exprss 为例:
const {
createRequestHandler,
} = require("@remix-run/express");
// 对所有的恳求,创建一个目标,供给上下文
app.all(
"*",
createRequestHandler({
getLoadContext(req, res) {
// this becomes the loader context
return { expressUser: req.user };
},
})
);
// 在 loader 中运用上下文
export async function loader({ context }: LoaderArgs) {
const { expressUser } = context;
// ...
}
loader 中重定向到
import { redirect } from "@remix-run/node";
export async function loader() {
return redirect('/abc')
}
export default function() {
return <div>loader.response</div>
}
在 loader函数中能运用 redirect 函数进行重定向
过错处理
- throw 一个指定 http 状况码,如 401:
throw json(
{ invoiceOwnerEmail: invoice.owner.email },
{ status: 401 }
);
- 运用
CatchBoundary
+useCatch
捕获过错
export function CatchBoundary() {
// this returns { data, status, statusText }
const caught = useCatch<ThrownResponses>();
switch (caught.status) {
case 401:
return (
<div>
<p>You don't have access to this invoice.</p>
<p>
Contact {caught.data.invoiceOwnerEmail} to get
access
</p>
</div>
);
case 404:
return <div>Invoice not found!</div>;
}
// You could also `throw new Error("Unknown status in catch boundary")`.
// This will be caught by the closest `ErrorBoundary`.
return (
<div>
Something went wrong: {caught.status}{" "}
{caught.statusText}
</div>
);
}
在页面中的表现
运用 loader 获取的数据,获取保存在 html 文档的window.__remixContext
目标里面。
loader 作为纯 api 输出数据运用
Remix 是一个全栈框架,loader 函数用于对外输出数据,这儿将 loader 界说为一个纯的 api 接口运用 loader 对外供给数据:
- 定于路由:
api.loader.tsx
export const loader = () => {
return {
a: 1
}
}
启动服务,直接拜访 /api/loader
接口得默许运用 get 方法 json 数据。假如要处理不同的恳求方法,能够在 loader 函数的参数中获取。
小结
从文中能够看到, Remix Loader 供给强大的数据处理能力,经过window.__remixContext
供给上下文, loder 中支持获取 json 数据, defer 异步数据,运用 Fetch API 的 Response 规范呼应一个数据。能运用自界说上下文,能重定向等等。