火力基地/NextJS:无法访问动态路由的子集合

8yparm6h  于 2023-01-30  发布在  其他
关注(0)|答案(1)|浏览(109)

我正在构建一个故事编辑器,您可以在其中编写故事并将它们分成不同的章节,但我在访问NextJS的"getStaticPaths"的子集合时遇到了麻烦,因为每个文档都是一个UUID。

    • 我将数据存储在Firebase Firestore中,如下所示:**
stories
├── UUID1 (Story 1)
│    └──chapters
│        └── UUID (Chapter 1)
│        └── UUID (Chapter 2)
│
│  
├── UUID2 (Story 1)
│    └──chapters
│        └── UUID (Chapter 1)
│        └── UUID (Chapter 2)
│
    • 问题**

我无法访问chapters子集合,因为我无法获取UUID。
通常,为了访问这些章节,我会创建一个useEffect钩子来将UUID存储到一个useState钩子中,这样我就可以像下面的代码那样发送一个查询:

const chaptersQ = query(
      collection(db, "stories", story.data().id, "chapters")
    );

不幸的是,在尝试创建动态路由时,"getStaticPaths"存在于main函数之前/之外,所以我不能使用react钩子。

    • 这是我当前的代码:**
export const getStaticPaths = async () => {
  const storyQ = collection(db, "stories");
  const queryStory = await getDocs(storyQ);

  queryStory.forEach(async (story) => {
    const chaptersQ = query(
      collection(db, "stories", story.data().id, "chapters")
    );
    const queryChapters = getDocs(chaptersQ);

    return {
      paths: (await queryChapters).docs?.map((doc) => ({
        params: {
          id: `${doc.data().storyID}`,
          chapter: `${doc.data().chapter}`,
        },
      })),
    };
  });
};

这将返回一个无效错误,因为路径不知何故接收到一个undefined。
我已经花了几个小时在这上面了,我得到的最接近的方法是在文件的根层声明一个带有"let"的变量,然后把www.example.com一章推到它里面。doc.data into it.
然后在return语句中使用它来设置路径和参数。但是,这也返回了未定义的错误。
先谢谢你!

nbysray5

nbysray51#

forEach方法不返回值,因此paths属性将无法正确设置,这意味着它将处于未定义状态。
在我看来,有2种方法可以得到理想的结果:
1.您可以使用map函数来创建路径数组,然后返回它,而不是使用forEach

export const getStaticPaths = async () => {
  const storyQ = collection(db, "stories");
  const queryStory = await getDocs(storyQ);

  const paths = await Promise.all(queryStory.map(async (story) => {
    const chaptersQ = query(
      collection(db, "stories", story.data().id, "chapters")
    );
    const queryChapters = await getDocs(chaptersQ);

    return queryChapters.docs.map((doc) => ({
      params: {
        id: `${doc.data().storyID}`,
        chapter: `${doc.data().chapter}`,
      },
    }));
  }));

  return {
    paths: paths.flat(),
  };
};

这应该正确地创建了paths数组,但是您可能需要根据您的特定用例对其进行调整。
1.使用async/await并创建一个空数组,然后将路径推入其中。

export const getStaticPaths = async () => {
  const storyQ = collection(db, "stories");
  const queryStory = await getDocs(storyQ);

  let paths = []
  for (const story of queryStory) {
    const chaptersQ = query(
      collection(db, "stories", story.data().id, "chapters")
    );
    const queryChapters = await getDocs(chaptersQ);

    for(const chapter of queryChapters.docs) {
      paths.push({
        params: {
          id: `${chapter.data().storyID}`,
          chapter: `${chapter.data().chapter}`,
        },
      });
    }
  }
  return {
    paths,
  };
};

如果让我选择使用哪种方法,我会选择第一种。因为Promise.all()给出了干净的代码。

相关问题