reactjs 我可以在Remix中为一个URL处理多个加载器吗?

bvn4nwqk  于 2022-12-18  发布在  React
关注(0)|答案(2)|浏览(138)

目前我有一个多节的登录页面,它是用Remix.run构建的。这些节是同一个URL的一部分,它们在同一个页面中垂直地一个接一个显示。
我的问题是,页面持续加载一段时间,因为加载器中有多个请求。每个部分需要从服务器不同的信息,但所有部分的所有请求都在同一个加载器中等待。
我可以为每个部分处理一个加载器吗?这样整个页面就不会等待所有请求完成,而是每个部分可以等待自己的数据
我已尝试将每个部分作为路径处理

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

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

const MyPage = (): React.ReactElement => (
  <main>
    <section>
      <Section1 />
    </section>
    <section>
      <Section2 />
    </section>
  </main>
)
export default MyPage;

但我得到了下一个错误

TypeError: Cannot destructure property 'myData' of '(0 , import_react7.useLoaderData)(...)' as it is undefined.


看起来Section 1组件正在尝试从MyPage加载程序获取数据,而不是从Section 1加载程序本身获取数据。
如果我在MyPage中使用<Outlet />组件,那么Section 1和Section 2加载器在我通过URL访问它们时可以工作

localhost:3000/my-page/section-1
localhost:3000/my-page/section-2

但我不希望部分嵌套路线,我希望他们在我的网页。
如果有人能帮我的话,我将非常感激。谢谢!

7eumitmz

7eumitmz1#

在混音中,**routes**目录下的所有内容都将作为浏览器中的“导航路线”/URL提供。

  • 我会尝试使用<Outlet />而不是<Section1 />。查看this remix documentation关于嵌套路由的内容。我读过几遍,有时会回头看,只是为了提醒自己Remix是如何处理嵌套路由的。*

如果您希望第1节和第2节出现在用户的同一路线上,则应从routes文件夹以外的其他位置导入React组分。您的节最好作为单独的React函数导入到您的路线中。

  • 应用程序/路线/我的页面.tsx*
import { Section1, Section2 } from "~/components/sections.tsx"
// ~ is a reference to the app directory. `~/routes` is also a valid path

// this function will be loaded when the requests comes in
export const loader: LoaderFunction = async ({request}) => {
   const myData = await fetch(random_api)
   return json({myData})
}
// this function will be returned to the browser
export default function MyPageRoute() {
   const myData = useLoaderData()
   return(
     <main>
       <section>
         <Section1 data={myData.section1} />
       </section>
       <section>
         <Section2 data={myData.section2} />
       </section>
     </main>
   )
}

我总是使用routes/目录之外的目录来存放我的react组件,我不希望它是一个路由。希望这对你有帮助:)

  • 编辑 * -忘记在react组件中添加数据属性
wnavrhmk

wnavrhmk2#

从技术上讲,每个URL可以有多个加载器,但是它们只能由一个路由模块导出(一个路由模块代表一个URL段)。
无论如何,这无助于加快页面加载速度,因为在呈现页面之前必须解析所有加载器。
因此,我要做的第一件事是确认您的“节”数据正在被并行请求。

// 🚨 Avoid this (serial)
const loader = async () => {
   const section1 = await fetchSection1();
   const section2 = await fetchSection2();
   const section3 = await fetchSection3();
   return json({ section1, section2, section3 });
}
// ✅ Prefer this (parallel)
const loader = async () => {
   const [section1, section2, section3] = await Promise.all([
      fetchSection1(),
      fetchSection2()
      fetchSection3()
   ]);
   return json({ section1, section2, section3 });
}

如果仍然很慢,下一步就是找出哪个部分需要很长时间。
如果有一两个调用特别慢,您最终将能够对数据进行defer,允许它在准备就绪之前进行回退。

然而在写这篇文章的时候,React Router的特性还没有登陆Remix

const loader = async () => {
  const [section1, section2] = await Promise.all([
    fetchSection1(),
    fetchSection2(),
  ]);
  return defer({
    section1,
    section2,
    // Notice we don't await fetchSection3 (as it's been identified as slow)
    section3: fetchSection3(),
  });
};

export default function Component() {
  const { section1, section2, section3 } = useLoaderData();
  return (
    <main>
      <section>
        <Section1 data={section1} />
      </section>
      <section>
        <Section2 data={section2} />
      </section>
      <section>
        <React.Suspense fallback={"Loading"}>
          <Await resolve={section3}>
            {(section3) => (
              <Section3 data={section3} />
            )}
          </Await>
        </React.Suspense>
      </section>
    </main>
  );
}


给定的defer在Remix中还不受支持,现在你可能需要在客户端创建一个resource routeuseFetcher
如果你发现所有的部分都一样慢,你需要加快DB / API调用,如果这不可能,你下一个最好的选择是看看http or server side caching

相关问题