在我的Next.js应用的App Router中,当在动态路由段之间导航时,为什么路由变化时useEffect不会执行?

前端开发 2026-07-10

我正在用Next.js 14搭建一个应用,并使用App Router。我有一个动态路由 /products/[id],并且在使用 useEffect,把 params.id 作为依赖,在用户切换到不同的产品时获取数据。

问题: 当我从 "/products/1" 使用 <Link> 导航到 "/products/2" 时,useEffect 不会重新运行。组件不会因新产品数据而重新渲染——页面仍然显示旧的产品。

app/products/[id]/page.tsx:

'use client';

import { useEffect, useState } from 'react';
import { useParams } from 'next/navigation';

interface Product {
  id: number;
  title: string;
  description: string;
}

export default function ProductPage() {
  const params = useParams();
  const id = params.id as string;
  const [product, setProduct] = useState<Product | null>(null);

  useEffect(() => {
    const fetchProduct = async () => {
      const res = await fetch(`https://dummyjson.com/products/${id}`);
      const data = await res.json();
      setProduct(data);
    };

    fetchProduct();
  }, [id]); // id is in deps array

  if (!product) return <p>Loading...</p>;

  return (
    <div>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
    </div>
  );
}

导航链接(在另一个组件中):

<Link href="/products/2">Go to Product 2</Link>

我尝试过:

  1. id 添加到 useEffect 的依赖数组中——仍然不会重新运行。
  2. 尝试使用 router.push('/products/2') 代替 <Link>——结果相同。
  3. 在父布局中的组件里添加 key={id}——这会强制进行一次完整的重新挂载,但我想了解为什么 useEffect 会自己不触发。
  4. 通过日志确认 params.id 确实会变化——它在渲染阶段有更新,但 useEffect 仍然不会触发。

预期行为: 每次 id 变化时(也就是用户切换到不同的产品),useEffect 应重新执行并获取新产品的数据。

实际行为: useEffect 仅在初始挂载时运行。导航到 "/products/2" 时会渲染组件,但副作用不会触发,因此仍显示旧的产品数据。

环境:

  • Next.js: 14.2.x
  • React: 18.x
  • TypeScript: 5.x
  • 使用App Router(非Pages Router)

这是Next.js 14 App Router与 useEffect 的已知问题吗?当动态路由参数变化时,如何正确获取数据?

解决方案

在Next.js 14中,正确的做法是将数据获取移到一个 Server Component。这将完全消除初始数据加载阶段对useEffect的需求

export default async function ProductPage({ params }: { params: { id: string } }) {
  const { id } = params;

  // Data fetching happens on the server
  const res = await fetch(`https://dummyjson.com/products/${id}`);
  const product = await res.json();

  return (
    <div>
      <h1>{product.title}</h1>
      <p>{product.description}</p>
    </div>
  );
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章