[英]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:在我看来,有两种方法可以获得所需的结果:
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.这应该正确创建路径数组,但您可能需要根据您的特定用例对其进行调整。
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.