在我的Next.js应用的App Router中,当在动态路由段之间导航时,为什么路由变化时useEffect不会执行?
我正在用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>
我尝试过:
- 将
id添加到useEffect的依赖数组中——仍然不会重新运行。 - 尝试使用
router.push('/products/2')代替<Link>——结果相同。 - 在父布局中的组件里添加
key={id}——这会强制进行一次完整的重新挂载,但我想了解为什么useEffect会自己不触发。 - 通过日志确认
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导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。