Remix 学习 - 路由模块(Route Module)

在 Remix 中,每个路由模块(Route Module)都可以包含多个导出,用于处理不同的功能。以下是每个路由模块主要的导出内容:

1. Component

  • 默认导出:每个路由模块通常会默认导出一个 React 组件。这是用于渲染该路由的页面。

    jsx 复制代码
    export default function MyPage() {
      return <h1>Hello, Remix!</h1>;
    }

2. Loader

  • 数据加载loader 函数用于在服务器端获取数据。它返回的数据可以在组件中使用。

    javascript 复制代码
      import { json } from "@remix-run/node";
      import { useLoaderData } from "@remix-run/react";
      
      export async function loader() {
        return json({ name: "Ryan", date: new Date() });
      }
      
      export default function SomeRoute() {
        const data = useLoaderData<typeof loader>();
      }
  • 此函数仅在服务器上运行。在初始服务器渲染时,它将向 HTML 文档提供数据。在浏览器中导航时,Remix 将通过fetch浏览器调用该函数。

  • 这意味着您可以直接与数据库对话,使用仅限服务器的 API 机密等。任何未用于呈现 UI 的代码都将从浏览器包中删除。

3. Action

  • 表单提交action 函数用于处理表单提交和其他 POST 请求。

    javascript 复制代码
    export async function action({ request }) {
      const formData = await request.formData();
      await saveData(formData);
      return redirect('/success');
    }
  • 路由 action 是服务器唯一功能,用于处理数据变化和其他操作。

  • 如果对路由发出非 GET 请求(DELETEPATCHPOSTPUT ),则在 loader 之前调用 action

4. Meta

  • 元数据meta 函数用于定义页面的元数据,如标题和描述。

    javascript 复制代码
      export const meta: MetaFunction = () => {
        return [
          { title: "Very cool app | Remix" },
          {
            property: "og:title",
            content: "Very cool app",
          },
          {
            name: "description",
            content: "This app is the best",
          },
        ];
      };

    生成如下 HTML:

    html 复制代码
      <title>Very cool app | Remix</title>
      <meta property="og:title" content="Very cool app" />;
      <meta name="description" content="This app is the best" />
  • 样式和链接links 函数用于加载 CSS 或链接其他资源。

    typescript 复制代码
      import type { LinksFunction } from "@remix-run/node"; // or cloudflare/deno
      
      export const links: LinksFunction = () => {
        return [
          {
            rel: "icon",
            href: "/favicon.png",
            type: "image/png",
          },
          {
            rel: "stylesheet",
            href: "https://example.com/some/styles.css",
          },
          { page: "/users/123" },
          {
            rel: "preload",
            href: "/images/banner.jpg",
            as: "image",
          },
        ];
      };

6. ErrorBoundary

  • 错误处理:用于捕获未处理的 JavaScript 错误,并提供错误信息。

    javascript 复制代码
      import { isRouteErrorResponse, useRouteError } from "@remix-run/react";
      
      export function ErrorBoundary() {
      	const error = useRouteError();
      	if (isRouteErrorResponse(error)) {
      	    return (
      	      <div>
      	        <h1>
      	          {error.status} {error.statusText}
      	        </h1>
      	        <p>{error.data}</p>
      	      </div>
      	    );
      	 } else if (error instanceof Error) {
      	    return (
      	      <div>
      	        <h1>Error</h1>
      	        <p>{error.message}</p>
      	        <p>The stack trace is:</p>
      	        <pre>{error.stack}</pre>
      	      </div>
      	    );
      	 } else {
      	    return <h1>Unknown Error</h1>;
      	 }
      }

7. CatchBoundary

  • 特定错误处理:用于处理特定 HTTP 错误,如 404。

    javascript 复制代码
      export function CatchBoundary() {
         let caught = useCatch();
         return (
           <div>
             <h1>Error {caught.status}</h1>
             <p>{caught.statusText}</p>
           </div>
         );
       }

8. Client Loader (clientLoader)

  • 客户端数据加载:用于在客户端进行数据加载,适合在页面交互后需要动态更新的数据。

  • 返回的数据用于客户端更新,不影响初始服务器端渲染。

  • 可以提供更好的用户体验,因为它避免了不必要的页面刷新和服务器负载。

    javascript 复制代码
    	export const clientLoader = async ({
    	  request,
    	  params,
    	  serverLoader,
    	}: ClientLoaderFunctionArgs) => {
    	  // call the server loader
    	  const serverData = await serverLoader();
    	  // And/or fetch data on the client
    	  const data = getDataFromClient();
    	  // Return the data to expose through useLoaderData()
    	  return data;
    	};

9. Client Action (clientAction)

  • 客户端表单处理 :在客户端处理表单提交,用于无刷新提交,无需与服务器交互。

    javascript 复制代码
    	export const clientAction = async ({
    	  request,
    	  params,
    	  serverAction,
    	}: ClientActionFunctionArgs) => {
    	  invalidateClientSideCache();
    	  const data = await serverAction();
    	  return data;
    	};

10. Handle

  • 路由元数据:用于传递自定义数据或配置到路由模块,比如页面标题、描述等,供其他部分(如布局组件、文档组件)使用。

    javascript 复制代码
      // 在路由模块中
      export let handle = {
        breadcrumb: 'Home',
        customData: { someKey: 'someValue' }
      };
      
      // 在其他地方使用 handle 数据
      export default function SomeRoute() {
        let data = useLoaderData();
        let handle = useRouteHandle();
      
        return (
          <div>
            <h1>{handle.breadcrumb}</h1>
            <p>{data.someData}</p>
          </div>
        );
      }

11. Headers

  • 自定义头部:定义页面的 HTTP 头部信息。

    javascript 复制代码
      import type { HeadersFunction } from "@remix-run/node"; // or cloudflare/deno
      
      export const headers: HeadersFunction = ({
        actionHeaders,
        errorHeaders,
        loaderHeaders,
        parentHeaders,
      }) => ({
        "X-Stretchy-Pants": "its for fun",
        "Cache-Control": "max-age=300, s-maxage=3600",
      });

12. HydrateFallback

  • 加载占位符 :用于在客户端渲染之前显示的占位内容。

    javascript 复制代码
     export async function clientLoader() {
       const data = await loadSavedGameOrPrepareNewGame();
       return data;
     }
     // Note clientLoader.hydrate is implied without a server loader
     
     export function HydrateFallback() {
       return <p>Loading Game...</p>;
     }
    
     export default function Component() {
       const data = useLoaderData<typeof clientLoader>();
       return <Game data={data} />;
     }

13. Should Revalidate (shouldRevalidate)

  • 重新验证:控制数据是否需要重新验证或刷新。

  • 此功能可让应用程序优化在 actions 以及客户端导航后,判断应重新加载哪些路由数据。

    javascript 复制代码
      import type { ShouldRevalidateFunction } from "@remix-run/react";
      
      export const shouldRevalidate: ShouldRevalidateFunction = ({
        actionResult,
        currentParams,
        currentUrl,
        defaultShouldRevalidate,
        formAction,
        formData,
        formEncType,
        formMethod,
        nextParams,
        nextUrl,
      }) => {
        return true;
      };

每个路由模块可以根据需要导出这些功能,以支持页面的不同需求。通过这些导出,Remix 提供了灵活的方式来处理数据、错误和页面渲染。

相关推荐
阿珊和她的猫1 小时前
v-scale-scree: 根据屏幕尺寸缩放内容
开发语言·前端·javascript
_Kayo_3 小时前
node.js 学习笔记3 HTTP
笔记·学习
加班是不可能的,除非双倍日工资6 小时前
css预编译器实现星空背景图
前端·css·vue3
wyiyiyi6 小时前
【Web后端】Django、flask及其场景——以构建系统原型为例
前端·数据库·后端·python·django·flask
CCCC13101636 小时前
嵌入式学习(day 28)线程
jvm·学习
gnip6 小时前
vite和webpack打包结构控制
前端·javascript
excel7 小时前
在二维 Canvas 中模拟三角形绕 X、Y 轴旋转
前端
星星火柴9367 小时前
关于“双指针法“的总结
数据结构·c++·笔记·学习·算法
小狗爱吃黄桃罐头7 小时前
正点原子【第四期】Linux之驱动开发篇学习笔记-1.1 Linux驱动开发与裸机开发的区别
linux·驱动开发·学习
阿华的代码王国7 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端