[英]Firebase/NextJS: Can't access subcollections for dynamic routing
我正在构建一个故事编辑器,您可以在其中编写故事并将它们分成不同的章节,并且我无法访问 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)
│
问题
我无法访问章节子集,因为我无法获取 UUID。
通常,为了访问这些章节,我创建了一个 useEffect 挂钩来将 UUID 存储到 useState 挂钩中,这样我就可以像下面的代码一样发送查询:
const chaptersQ = query(
collection(db, "stories", story.data().id, "chapters")
);
不幸的是,在尝试创建动态路由时,“getStaticPaths”存在于主要 function 之前/之外,因此我无法使用反应钩子。
这是我当前的代码:
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}`,
},
})),
};
});
};
这将返回一个无效错误,因为路径以某种方式收到未定义的错误。
我花了几个小时来研究这个。 我得到的最接近的方法是在文件的根层中声明一个带有“let”的变量,然后将 chapter doc.data 推入其中。
然后在返回语句中使用它来设置路径和参数。 但是,这也返回了未定义的错误。
先感谢您!
forEach
方法不返回值,因此不会正确设置paths
属性,这意味着它将是未定义的。
在我看来,有两种方法可以获得所需的结果:
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(),
};
};
这应该正确创建路径数组,但您可能需要根据您的特定用例对其进行调整。
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()
给出了干净的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.