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

NextJS中不使用Props向动态页面传递数据的方法求助

问题原因分析

React Context 仅在同一 React 组件树内生效,而 NextJS 中页面跳转后,原页面组件会被卸载,新页面是独立的根组件,因此无法跨页面读取之前的 Context 值。

以下是几种无需重复请求数据的解决方案:


方案1:URL传ID + NextJS 请求缓存

通过 URL 传递项目 ID,利用 NextJS 的缓存机制避免重复请求:

步骤1:在详情页传递ID

修改 projectInfo.jsx 的跳转链接:

<Link
  href={{ pathname: '/Report', query: { projectId: id } }}
>
  <span className="mt-2 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
    Create Report
  </span>
</Link>

步骤2:报表页读取缓存数据

在 Report.jsx 中,通过带缓存的 fetch 复用之前的请求结果:

export default function ReportPage({ searchParams }) {
  const [project, setProject] = useState(null);

  useEffect(() => {
    if (!searchParams.projectId) return;
    // 开启强制缓存,复用之前的请求结果
    fetch(`/projects/get/${searchParams.projectId}`, { cache: 'force-cache' })
      .then(res => res.json())
      .then(data => setProject(data))
      .catch(err => console.error('获取数据失败:', err));
  }, [searchParams.projectId]);

  return (
    <div>
      {project && (
        <div>
          <h2>报表:{project.title}</h2>
          {/* 渲染报表内容 */}
        </div>
      )}
    </div>
  );
}

如果使用 App Router 的 Server Components,可直接在组件内调用缓存的请求:

async function ReportPage({ searchParams }) {
  // NextJS 会自动缓存该请求,无需额外配置
  const res = await fetch(`/projects/get/${searchParams.projectId}`);
  const project = await res.json();

  return <div>{/* 报表内容 */}</div>;
}

方案2:客户端本地存储(localStorage/sessionStorage)

将详情页请求到的数据存入本地存储,报表页直接读取:

步骤1:详情页存储数据

修改 projectInfo.jsx 的 fetch 回调:

.then((data) => {
  setProject(data);
  // 存入localStorage,用ID作为键名避免冲突
  localStorage.setItem(`project_${id}`, JSON.stringify(data));
})

步骤2:报表页读取缓存

在 Report.jsx 中优先读取本地存储,可选静默刷新数据:

export default function ReportPage({ searchParams }) {
  const [project, setProject] = useState(null);

  useEffect(() => {
    if (!searchParams.projectId) return;
    const cacheKey = `project_${searchParams.projectId}`;
    const cachedData = localStorage.getItem(cacheKey);

    if (cachedData) {
      // 直接使用缓存数据
      setProject(JSON.parse(cachedData));
      // 可选:后台静默刷新数据,更新缓存
      fetch(`/projects/get/${searchParams.projectId}`)
        .then(res => res.json())
        .then(freshData => {
          setProject(freshData);
          localStorage.setItem(cacheKey, JSON.stringify(freshData));
        });
    } else {
      // 缓存不存在时发起请求
      fetch(`/projects/get/${searchParams.projectId}`)
        .then(res => res.json())
        .then(data => {
          setProject(data);
          localStorage.setItem(cacheKey, JSON.stringify(data));
        });
    }
  }, [searchParams.projectId]);

  return (
    <div>
      {project && <div>报表内容:{/* ... */}</div>}
    </div>
  );
}

方案3:App Router 专属 React Cache

如果使用 NextJS 13+ 的 App Router,可通过 React 内置的 cache 函数实现跨组件请求复用:

步骤1:定义缓存请求函数

创建 lib/projects.js:

import { cache } from 'react';

export const getProject = cache(async (projectId) => {
  const res = await fetch(`/projects/get/${projectId}`);
  if (!res.ok) throw new Error('获取项目数据失败');
  return res.json();
});

步骤2:详情页调用

async function ProjectInfoPage({ params }) {
  const project = await getProject(params.id);

  return (
    <div>
      <h1>{project.title}</h1>
      <Link href={`/Report?projectId=${params.id}`}>Create Report</Link>
    </div>
  );
}

步骤3:报表页调用

async function ReportPage({ searchParams }) {
  // 复用之前的缓存结果,不会重复发起请求
  const project = await getProject(searchParams.projectId);

  return <div>{/* 报表内容 */}</div>;
}

内容的提问来源于stack exchange,提问作者Sid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:56:38