You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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中匹配对应数据。

  1. 创建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;
}
  1. 根布局中包裹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>
  );
}
  1. 列表页存入数据到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>
  );
}
  1. 目标页从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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 17:20:15