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

Next.js宠物救助站项目:按钮跳转页面出现404错误求助

解决Next.js宠物详情页跳转404问题

你的问题主要出在路由文件结构不匹配、Link组件用法错误以及服务器组件与客户端钩子冲突这几个点,以下是分步解决方法:

1. 调整路由文件结构

首先确保详情页的文件路径和跳转路径严格对应:

  • 若使用Pages Router(Next.js 12及更早,或13+兼容模式):将PetDetailPage文件放在pages/adote/[petId].js
  • 若使用App Router(Next.js 13+):将PetDetailPage放在app/adote/[petId]/page.js

这是404错误的核心原因——Next.js无法找到对应路径的页面组件。

2. 修正PetCard的Link组件

你当前用的是旧版Pages Router的as属性写法,且跳转路径和实际路由不匹配,改成直接指定动态路径:

import React from 'react';
import Image from 'next/image';
import Button from '../components/Button';
import Link from 'next/link';

export default function PetCard({ pet }) {
  return (
    <div className="flex flex-col border p-4 rounded-lg hover:shadow-lg transition-shadow bg-white" >
      {/* 直接用pet.id作为动态参数,路径和路由文件对应 */}
      <Link href={`/adote/${pet.id}`}>
        <Button
          label="Ver perfil"
          className="bg-indigo-500 hover:bg-gray-600 focus-visible:outline-indigo-600 w-32 flex flex-row justify-center items-center"
        />
      </Link>
    </div>
  )
}
  • 去掉passHref和onClick:Next.js 13+的Link组件可直接包裹按钮,无需额外属性;跳转逻辑由Link处理,不需要单独的onClick事件。

3. 修复PetDetailPage的逻辑

如果你用Pages Router:

去掉'use server'标识(useRouter是客户端钩子,不能在服务器组件中使用),并通过getServerSideProps获取宠物数据:

import React from 'react';
import { useRouter } from 'next/router';
import Image from 'next/image';

export default function PetDetailPage({ pet }) {
  if (!pet) return <p>宠物未找到</p>;
  
  return (
    <div className="p-4">
      <Image src={pet.avatar} alt={pet.name} width={600} height={600} className="rounded-md" />
      <h1 className="text-2xl font-bold mt-4">{pet.name}</h1>
      <p className="text-gray-600">{pet.breed}</p>
      <p className="text-gray-600">{pet.id}</p>
      <p className="text-gray-600">{pet.age}</p>
      <p className="text-gray-600">{pet.gender}</p>
      <p className="mt-2">{pet.description}</p>
    </div>
  );
}

// 服务器端获取宠物数据
export async function getServerSideProps(context) {
  const { petId } = context.query;
  try {
    const res = await fetch(`https://mockID.mockapi.io/pets/${petId}`);
    const pet = await res.json();
    return { props: { pet } };
  } catch (err) {
    return { props: { pet: null } };
  }
}

如果你用App Router:

添加'use client'标识(useParams是客户端钩子),通过useParams获取petId并请求数据:

'use client';
import React, { useState, useEffect } from 'react';
import { useParams } from 'next/navigation';
import Image from 'next/image';

export default function PetDetailPage() {
  const { petId } = useParams();
  const [pet, setPet] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchPet = async () => {
      try {
        const res = await fetch(`https://mockID.mockapi.io/pets/${petId}`);
        const data = await res.json();
        setPet(data);
      } catch (err) {
        setPet(null);
      } finally {
        setLoading(false);
      }
    };
    fetchPet();
  }, [petId]);

  if (loading) return <p>加载中...</p>;
  if (!pet) return <p>宠物未找到</p>;

  return (
    <div className="p-4">
      <Image src={pet.avatar} alt={pet.name} width={600} height={600} className="rounded-md" />
      <h1 className="text-2xl font-bold mt-4">{pet.name}</h1>
      <p className="text-gray-600">{pet.breed}</p>
      <p className="text-gray-600">{pet.id}</p>
      <p className="text-gray-600">{pet.age}</p>
      <p className="text-gray-600">{pet.gender}</p>
      <p className="mt-2">{pet.description}</p>
    </div>
  );
}

4. 清理Adote页面的冗余代码

因为已经通过Link处理跳转,所以删掉Adote页面中无用的handlePetClick函数,以及PetCard的onClick传参:

// 删掉这段冗余代码
const handlePetClick = (petId) => {
  router.push(`/adote/${petId}`)
}

// PetCard调用改为
<PetCard key={pet.id} pet={pet} />

另外,Adote页面中你未导入router却使用了它,现在删掉相关代码后也无需再导入。

按以上步骤调整后,跳转和详情页展示就能正常工作了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 15:40:04