我可以在 Remix 中处理单个 URL 的多个加载器吗?

And*_*ino 4 routes nested-routes reactjs remix remix.run

目前我有一个包含多个部分的登陆页面,它是使用 Remix.run 构建的。这些部分是同一 URL 的一部分,它们在同一页面中垂直相邻显示。

我的问题是该页面需要一段时间才能加载,因为加载器中完成了多个请求。每个部分都需要来自服务器的不同信息,但所有部分的所有请求都在同一个加载器中等待。

我可以为每个部分处理一个加载程序吗?因此整个页面不会等待所有请求完成,但每个部分都可以等待自己的数据

我已经尝试将每个部分作为一条路线来处理

> routes
  > my-page.tsx
  > my page
    > section-1.tsx
    > section-2.tsx

Run Code Online (Sandbox Code Playgroud)

然后我尝试为每个部分添加一个加载器,并调用 my-page.tsx 中的部分

我的页面.tsx

const MyPage = (): React.ReactElement => (
  <main>
    <section>
      <Section1 />
    </section>
    <section>
      <Section2 />
    </section>
  </main>
)
export default MyPage;
Run Code Online (Sandbox Code Playgroud)

但我收到下一个错误

TypeError: Cannot destructure property 'myData' of '(0 , import_react7.useLoaderData)(...)' as it is undefined.
Run Code Online (Sandbox Code Playgroud)

看起来Section1 组件正在尝试从MyPage 加载器获取数据,而不是从Section1 加载器本身获取数据。

如果我在 MyPage 中使用该<Outlet />组件,则通过 URL 访问Section1 和Section2 加载器即可工作

localhost:3000/my-page/section-1
localhost:3000/my-page/section-2
Run Code Online (Sandbox Code Playgroud)

但我不希望这些部分是嵌套路由,我希望它们位于我的页面中。

如果有人能帮助我,我将非常感激。谢谢你!

ris*_*ott 6

从技术上讲,每个 url 可以有多个加载器,但是它们只能由路由模块导出(路由模块代表单个 URL 段)。

\n

无论如何,这无助于加快页面加载速度,因为在呈现页面之前必须解析所有加载器。

\n

因此,我要做的第一件事是确认您的“部分”数据正在被并行请求。

\n
//  Avoid this (serial)\nconst loader = async () => {\n   const section1 = await fetchSection1();\n   const section2 = await fetchSection2();\n   const section3 = await fetchSection3();\n   return json({ section1, section2, section3 });\n}\n
Run Code Online (Sandbox Code Playgroud)\n
// \xe2\x9c\x85 Prefer this (parallel)\nconst loader = async () => {\n   const [section1, section2, section3] = await Promise.all([\n      fetchSection1(),\n      fetchSection2()\n      fetchSection3()\n   ]);\n   return json({ section1, section2, section3 });\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果仍然很慢,下一步就是找出哪个部分花费了很长时间。

\n

如果有一两个调用特别慢,您最终将能够获取defer数据,允许它渲染回退,直到准备好为止。

\n

然而,在撰写本文时,React Router 功能尚未登陆 Remix

\n
const loader = async () => {\n  // Notice we don\'t await fetchSection3 (as it\'s been identified as slow)\n  const section3 = fetchSection3();\n  const [section1, section2] = await Promise.all([\n    fetchSection1(),\n    fetchSection2(),\n  ]);\n  return defer({\n    section1,\n    section2,\n    section3, // Promise\n  });\n};\n\nexport default function Component() {\n  const { section1, section2, section3 } = useLoaderData();\n  return (\n    <main>\n      <section>\n        <Section1 data={section1} />\n      </section>\n      <section>\n        <Section2 data={section2} />\n      </section>\n      <section>\n        <React.Suspense fallback={"Loading"}>\n          <Await resolve={section3}>\n            {(section3) => (\n              <Section3 data={section3} />\n            )}\n          </Await>\n        </React.Suspense>\n      </section>\n    </main>\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n

deferRemix 尚不支持给定。您现在可能必须在客户端中创建资源路由useFetcher

\n

如果您发现所有部分都同样慢,则需要加快 DB/API 调用速度。如果这是不可能的,那么您的下一个最佳选择是查看http 或服务器端缓存

\n