如何利用Firestore生成的文档ID创建标题+ID格式的Slug?
如何用Firestore文档ID生成包含标题的Slug并完成重定向
你当前的问题核心是:调用addDocument时还未获取到Firestore生成的文档ID,直接在创建文档阶段赋值slug会因id未定义而失效。正确流程是先创建基础文档,拿到ID后再生成并更新slug字段,具体实现如下:
解决步骤
- 先创建不带slug的基础文档:先传入除slug外的所有字段,获取Firestore返回的文档实例以拿到ID
- 生成URL友好的Slug:将标题处理为小写、替换空格为连字符、移除特殊字符的格式,再拼接文档ID(避免标题重复导致slug冲突)
- 更新文档的slug字段并重定向:用获取到的ID更新文档的slug属性,最后跳转到slug对应的页面
修改后的完整代码
const StartCodingButton = ({ document, setIsOpen }) => { const { user } = useAuthContext() // 确保useFirestore钩子提供updateDocument方法(基于Firestore的doc().update()实现) const { addDocument, updateDocument, response } = useFirestore("solutions") const { push } = useRouter() const { documents } = useCollection( "solutions", solutionDetails[0].challengeID ) // 工具函数:将标题转为URL友好的字符串 const formatSlugTitle = (title) => { return title .toLowerCase() .trim() .replace(/[^a-z0-9]+/g, '-') // 把非字母数字的字符替换为连字符 .replace(/^-+|-+$/g, '') // 移除首尾多余的连字符 } const initializeCodeEditor = async () => { if (documents.length > 0) { setIsOpen(false) // 已有文档时优先用slug,没有则退用ID push(`/playground/${documents[0].slug || documents[0].id}`) } else { // 1. 创建基础文档,暂不设置slug const addedDocument = await addDocument({ ...document, author: user.displayName !== null ? user.displayName : user.reloadUserInfo.screenName, userID: user.uid }) if (addedDocument) { const docId = addedDocument.id // 2. 生成最终slug:格式化后的标题 + 文档ID const formattedTitle = formatSlugTitle(document.title) const finalSlug = `${formattedTitle}-${docId}` // 3. 更新文档的slug字段 await updateDocument(docId, { slug: finalSlug }) setIsOpen(false) // 4. 跳转到slug对应的页面 push(`/playground/${finalSlug}`) } } } }
关键说明
- 需确认你的
useFirestore钩子包含updateDocument方法,若没有可自行基于Firestore原生API实现:updateDocument = async (id, data) => await doc(db, "solutions", id).update(data) - 格式化标题的规则可根据需求调整,比如保留特定符号或调整分隔符
- 重定向时使用生成好的
finalSlug,既保证URL可读性,又通过文档ID确保唯一性
内容的提问来源于stack exchange,提问作者r121
相关产品推荐
相关产品推荐

