简体   繁体   English

Firebase/NextJS:无法访问动态路由的子集合

[英]Firebase/NextJS: Can't access subcollections for dynamic routing

I'm building a story editor where you can write stories and separate them into different chapters and I'm having trouble accessing my subcollection for NextJS's "getStaticPaths" because every document is a UUID.我正在构建一个故事编辑器,您可以在其中编写故事并将它们分成不同的章节,并且我无法访问 NextJS 的“getStaticPaths”的子集合,因为每个文档都是一个 UUID。

I have data stored in a Firebase Firestore like this:我将数据存储在 Firebase Firestore 中,如下所示:

stories
├── UUID1 (Story 1)
│    └──chapters
│        └── UUID (Chapter 1)
│        └── UUID (Chapter 2)
│
│  
├── UUID2 (Story 1)
│    └──chapters
│        └── UUID (Chapter 1)
│        └── UUID (Chapter 2)
│   

Problem问题

I can't access the chapters subcollection because I can't fetch the UUIDs.我无法访问章节子集,因为我无法获取 UUID。

Normally, to access the chapters, I create a useEffect hook to store the UUID into a useState hook so I can send a query like the code below:通常,为了访问这些章节,我创建了一个 useEffect 挂钩来将 UUID 存储到 useState 挂钩中,这样我就可以像下面的代码一样发送查询:

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

Unfortunately, in trying to create dynamic routing and "getStaticPaths" exist before/outside the main function, so I can't use react hooks.不幸的是,在尝试创建动态路由时,“getStaticPaths”存在于主要 function 之前/之外,因此我无法使用反应钩子。

Here's my current code:这是我当前的代码:

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}`,
        },
      })),
    };
  });
};

This returns an invalid error, as the paths somehow receive an undefined.这将返回一个无效错误,因为路径以某种方式收到未定义的错误。

I've spent hours working on this.我花了几个小时来研究这个。 The closest I've gotten is by declaring a variable with "let" in the root layer of the file and then pushing chapter doc.data into it.我得到的最接近的方法是在文件的根层中声明一个带有“let”的变量,然后将 chapter doc.data 推入其中。

Then using that in the return statement to set the paths and parameters.然后在返回语句中使用它来设置路径和参数。 However, this also returned and undefined error.但是,这也返回了未定义的错误。

Thank you in advance!先感谢您!

The forEach method does not return a value, so the paths property will not be set correctly, meaning it will be undefined. forEach方法不返回值,因此不会正确设置paths属性,这意味着它将是未定义的。

In my opinion there are 2 ways you can get the desired result:在我看来,有两种方法可以获得所需的结果:

  1. Instead of forEach , you can use the map function to create an array of paths and then return it.您可以使用map function 而不是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(),
  };
};

This should correctly create the paths array, but you may need to adjust it to your specific use case.这应该正确创建路径数组,但您可能需要根据您的特定用例对其进行调整。

  1. Using async/await and creating an empty array and then push the paths in it.使用 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,
  };
};

If I were given the choice of picking which approach to be used I would choose the 1st one.如果让我选择使用哪种方法,我会选择第一种。 As Promise.all() gives clean code.由于Promise.all()给出了干净的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Nextjs 动态路由在 firebase 主机中不起作用 - Nextjs dynamic routing not working in firebase hosting ReactJS、Firebase - Firestore,子集合的动态读取问题 - ReactJS, Firebase - Firestore, issue with the dynamic read of subcollections 我无法访问 firestore 数据库中的两个子集合之一。 反应 - I can't access one of two subcollections in firestore data base. React Arrays 或 Firebase Firestore 中的子集合? - Arrays or subcollections in Firebase Firestore? Firebase Firestore 规则子集合 - Firebase Firestore Rules Subcollections 无法获取 Firebase 动态链接 - Can't get Firebase Dynamic Link 如何删除 firebase 和 flutter 和 dart 中所有子集合的文档 - How can I delete a document with all its subcollections in firebase with flutter and dart 将 nextjs monorepo 项目与 lerna 一起使用时,无法解析 firebase-admin/lib 中的“fs” - Can't resolve 'fs' in firebase-admin/lib' when using nextjs monorepo project with lerna Firebase 规则——无法访问我的收藏 - Firebase rules -- can't access my collection 无法通过 web 上的 Firebase 存储访问上传的文件 - Can't access uploaded files through Firebase storage on web
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM