Next.js中如何通过next-navigation无查询串传递页面数据?
问题背景
Next.js 项目结构
src\ app\ directors\ page.tsx [director]\ page.tsx
directors/page.tsx 核心代码
import { useRouter } from "next/navigation"; const router = useRouter() {data.directors.map((director: any, childIndex: number) => ( <div key={childIndex} className="manager"> <a onClick={() => router.push(`${getBasePath()}/${lang}/directors/${director.subUrl}`}> <img src="xxx" alt="" /> </a> </div> ))}
问题:使用next/navigation的useRouter时,无法在不借助查询字符串的情况下将已获取的数据传递到[director]/page.tsx;之前尝试旧版next/router时出现挂载错误,想知道有没有可行的无查询串传数据方法。
可行解决方案
方案1:服务器组件重新获取数据(推荐)
App Router的设计核心是服务端优先,既然已经拿到director.subUrl,直接在目标页面的服务器组件中根据该参数重新请求完整数据即可,无需前端传递。
示例([director]/page.tsx作为服务器组件):
async function DirectorPage({ params }: { params: { director: string } }) { // 用url中的subUrl请求对应数据 const directorData = await fetchDirectorData(params.director); return ( <div> {/* 渲染directorData内容 */} </div> ); } export default DirectorPage;
这种方式符合Next.js设计理念,避免前端状态同步问题,且服务器请求不会暴露给客户端,安全性更高。
方案2:React Context 客户端状态管理
如果不想重复请求,可通过React Context存储已获取的导演列表,目标页面根据subUrl从Context中匹配对应数据。
- 创建Context:
// app/contexts/DirectorContext.tsx "use client"; import { createContext, useContext, useState, ReactNode } from "react"; type Director = { subUrl: string; // 其他数据字段 }; type DirectorContextType = { directors: Director[]; setDirectors: (directors: Director[]) => void; }; const DirectorContext = createContext<DirectorContextType | undefined>(undefined); export function DirectorProvider({ children }: { children: ReactNode }) { const [directors, setDirectors] = useState<Director[]>([]); return ( <DirectorContext.Provider value={{ directors, setDirectors }}> {children} </DirectorContext.Provider> ); } export function useDirectorContext() { const context = useContext(DirectorContext); if (!context) { throw new Error("useDirectorContext必须在DirectorProvider范围内使用"); } return context; }
- 根布局中包裹Provider:
// app/layout.tsx import { DirectorProvider } from "./contexts/DirectorContext"; export default function RootLayout({ children }: { children: ReactNode }) { return ( <html lang="zh-CN"> <body> <DirectorProvider>{children}</DirectorProvider> </body> </html> ); }
- 列表页存入数据到Context:
"use client"; import { useRouter, useEffect } from "next/navigation"; import { useDirectorContext } from "../contexts/DirectorContext"; type Director = { subUrl: string; // 其他字段 }; export default function DirectorsPage({ data }: { data: { directors: Director[] } }) { const router = useRouter(); const { setDirectors } = useDirectorContext(); useEffect(() => { setDirectors(data.directors); }, [data.directors, setDirectors]); return ( <div> {data.directors.map((director: Director, childIndex: number) => ( <div key={childIndex} className="manager"> <a onClick={() => router.push(`${getBasePath()}/${lang}/directors/${director.subUrl}`)}> <img src="xxx" alt="" /> </a> </div> ))} </div> ); }
- 目标页从Context匹配数据:
"use client"; import { useParams } from "next/navigation"; import { useDirectorContext } from "../../contexts/DirectorContext"; export default function DirectorPage() { const params = useParams(); const { directors } = useDirectorContext(); const directorData = directors.find(d => d.subUrl === params.director); if (!directorData) { return <div>未找到导演信息</div>; } return ( <div> {/* 渲染directorData内容 */} </div> ); }
注意:若用户直接访问目标页而非从列表页跳转,Context中无数据,需做降级处理(如重新请求)。
方案3:加密查询参数(备选,不推荐)
若不想用明文查询串,可将数据加密后作为参数传递,目标页解密。本质仍依赖查询串,仅隐藏内容,适合小体量数据:
列表页代码:
// 假设encrypt是自定义加密函数 const encryptedData = encrypt(JSON.stringify(director)); router.push(`${getBasePath()}/${lang}/directors/${director.subUrl}?data=${encryptedData}`);
目标页代码:
"use client"; import { useSearchParams } from "next/navigation"; export default function DirectorPage() { const searchParams = useSearchParams(); const encryptedData = searchParams.get("data"); const directorData = encryptedData ? JSON.parse(decrypt(encryptedData)) : null; // 渲染逻辑 }
该方式存在查询参数长度限制,且增加加密解密复杂度,不推荐使用。
关于旧版next/router的挂载错误
旧版next/router是为Pages Router设计的,与App Router路由系统不兼容,因此在App Router项目中必须使用next/navigation提供的API,否则会出现挂载错误。
内容的提问来源于stack exchange,提问作者MERN Stack Developer
相关产品推荐
相关产品推荐

