router.query获取URL参数返回undefined,是否因路由未就绪导致?
Next.js中router.query获取artistId始终为undefined的解决方案
你的猜测没错,问题确实是路由未就绪时页面就尝试读取router.query导致的。Next.js在客户端初始化阶段,router.query不会立即填充完成,尤其是在页面首次加载或客户端导航的初期,这时候直接解构artistId就会得到undefined。
以下是具体的修复方案:
核心修复步骤
- 等待路由就绪再执行数据请求:利用
router.isReady状态判断路由是否完全加载完成,避免在未就绪时读取空的query参数。 - 修正useEffect依赖项:移除不必要的依赖,避免无限循环。
- 正确处理Firestore数据:文档快照需要调用
.data()获取实际数据,同时判断文档是否存在。 - 避免空值访问错误:初始状态下artist为空,需用可选链或条件渲染防止报错。
修改后的完整代码
import React, { useEffect, useState } from "react"; import { useSession } from "next-auth/react"; import { useRouter } from "next/router"; import { getDoc, doc } from "firebase/firestore"; import { db } from "../api/auth/firebase/config"; import Head from "next/head"; import ArtistHeader from "../../components/ArtistHeader"; import UploadButton from "../../components/UploadButton"; import styles from "../../styles/artistPage.module.css"; export default function Artist() { const { data: session, status } = useSession(); const [artist, setArtist] = useState(null); const router = useRouter(); const { artistId } = router.query; useEffect(() => { if (status === "unauthenticated") { router.push("/auth/signin"); } }, [status, router]); // 修正后的数据请求逻辑 useEffect(() => { // 路由未就绪或无artistId时直接返回 if (!router.isReady || !artistId) return; const fetchArtist = async () => { try { const artistRef = doc(db, "users", artistId); const docSnap = await getDoc(artistRef); if (docSnap.exists()) { setArtist(docSnap.data()); } else { console.log("该艺术家不存在"); // 可选:跳转到404页面 // router.push("/404"); } } catch (err) { console.error("获取艺术家数据失败:", err); } }; fetchArtist(); }, [router.isReady, artistId, router]); // 加载状态处理 if (!artist) { return <div>加载中...</div>; } return ( <section className={styles.wrapper}> <Head> <title>{artist.screenName || "艺术家页面"}</title> </Head> <div className={styles.artistPage}> <ArtistHeader artist={artist} /> <div className={styles.songContainer}> <UploadButton /> </div> </div> </section> ); }
额外注意事项
- 若页面使用静态生成(SSG),可改用
getStaticProps+getStaticPaths在服务端预获取数据,彻底规避客户端路由就绪问题。 - 如果你使用Next.js 13+的App Router,路由参数需通过
useParams()获取,逻辑会有所不同,但当前Pages Router的方案完全适用。
内容的提问来源于stack exchange,提问作者Yan
相关产品推荐
相关产品推荐

