如何让NextJS中的按钮转到我在同一应用中创建的另一个页面?

sd2nnvve  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(64)

对于contenxt,我正在为一个宠物救援慈善机构建立一个网站,我正在使用Next.js。我是Nextjs的新手,不知道如何让我的按钮或链接到实际工作的propective.I目前得到一个404错误此页面无法找到,当我试图让按钮带我到另一个页面,我已经建立在我的下一个应用程序。
我试过几种方法。
有人能帮忙吗?”
这里是卡组件:

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

export default function PetCard({ pet, onClick }) {

  return (
    <div className="flex flex-col border p-4 rounded-lg hover:shadow-lg transition-shadow bg-white" >
      <Link href="/[petId]" as={`/adote/${pet.name}`} passHref>
        <Button
          label="Ver perfil"
          onClick={onClick}
          className="bg-indigo-500 hover:bg-gray-600 focus-visible:outline-indigo-600 w-32 flex flex-row justify-center items-center"
        /></Link>

    </div>
  )
}

字符串
该按钮应该转到此petId页面:

'use server'
import React from 'react';
import { useRouter } from 'next/router';

export default function PetDetailPage() {
  const router = useRouter();
  const pet = JSON.parse(router.query);
 
  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>
  );
}


我不介意它现在只是一个占位符页面。我有这个来自我制作的模拟API的模拟数据,它在主采用页面上没有任何问题:

'use client';

import React from 'react';
import CustomizableHero from "../../components/HeroScondary";
import PetCard from "../../components/PetCard";
import Button from '../../components/Button';
import { useState, useEffect } from 'react'

export default function Adote() {
  // mock API
  const [pets, setPets] = useState([])
  const [loading, setLoading] = useState(true)
  const [page, setPage] = useState(1)

  useEffect(() => {
    const fetchPets = async () => {
      setLoading(true)
      const url = new URL('https://mockID.mockapi.io/pets')

      url.searchParams.append('completed', false)
      url.searchParams.append('page', page)
      url.searchParams.append('limit', 18)
      
      const res = await fetch(url)      
      const data = await res.json()
      setPets(prevPets => [...prevPets, ...data])
      setLoading(false)

    }
    fetchPets()
  },
    [])

  if (loading) {
    return <p>Loading...</p>
  }

  const handlePetClick = (petId) => {
    router.push(`/adote/${petId}`)
  }

  return (
    <div className="relative">
      <CustomizableHero
        backgroundImage="/images/dois-cachorros.png"
        title="Adote"
        subtitle="Encontre o seu melhor amigo"
        color="white"
      />
      {/* search filter */}
      <div className="flex flex-row">
      </div>
      {/* pet cards */}
      <div className="absolute w-[100vw] max-w-screen flex flex-col justify-center ">
        <div className="flex flex-col text-align-center items-center justify-between m-10">
          <h2 className="text-5xl font-bold tracking-tight sm:text-5xl text-gray-500 p-5">Animais buscando uma familia</h2>
          <p className="mt-6 mb-3 text-md leading-8 text-gray-500 text-center p-5">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec euismod, nulla ut condimentum maximus, felis enim rhoncus justo, vel venenatis magna tortor nec tortor. Donec vulputate fermentum fermentum. Curabitur odio dui, consectetur vitae ornare eu, ultricies vel risus</p>
        </div>
        {/* Called displayPetCards() inside JSX code to render the PetCard components. */}
        <div className="grid grid-cols-3 gap-4 m-10 p-5">
          {pets.map(pet => (
            <PetCard
              key={pet.id}
              pet={pet}
              onClick={()=> handlePetClick(pet.id)}
            />
          ))}
        </div>
        <p className="flex flex-col text-center mt-5">Visualizados 18 de 661 animais de estimação</p>
        <div className="flex justify-center m-10">
          <Button
            label="Mostrar mais"
            onClick={() => setPage(page + 1)
            }  // Attach the click handler here
            className="bg-indigo-500 hover:bg-gray-600 focus-visible:outline-indigo-600"
          />
        </div>
      </div>
    </div>
  );
};


我试过useRouter,我试过getServerSideProps(),但都不起作用

mrphzbgm

mrphzbgm1#

不要把事情复杂化,你已经在petCard组件中传递了pet.id,只是从那里链接它。

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

export default function PetCard({ pet, onClick }) {

 return (
  <div className="flex flex-col border p-4 rounded-lg hover:shadow-lg 
    transition-shadow bg-white" >
  <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>
  )
 }

字符串
然后通过参数在PetDetailPage中搜索pet的具体id

'use server'
import React from 'react';

export default function PetDetailPage({ params }) {
const pet = getPetDetails(params.id)

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>
 );
}

lfapxunr

lfapxunr2#

下面是我做的一个示例代码:解释:

  • 有一个显示所有宠物名称的宠物页面,
  • 它包含两个元素1st is Link tag2nd is a Button as link
  • 看一下文件夹结构,重点pets folder
  • 在宠物页面上,我已经显示了宠物数据(你可以使用你的卡组件显示它),使用你的代码中的URL。
    文件夹结构:
projectName
├── .gitignore
├── jsconfig.json
├── next.config.js
├── package-lock.json
├── package.json
├── postcss.config.js
├── public
│   ├── images
│   ├── next.svg
│   └── vercel.svg
├── README.md
├── src
│   └── app
│       ├── api
│       ├── comp
│       │   ├── LinkButton.js
│       ├── favicon.ico
│       ├── globals.css
│       ├── layout.js
│       ├── page.js
│       ├── pets
│       │   ├── page.js
│       │   └── [id]
│       │       └── page.js
└── tailwind.config.js

字符串

  • 现在我将显示宠物数据,并从它我将通过ID链接标签和按钮组件。
  • 按钮组件是事件点击的客户端组件。
  • 现在,如果有人点击链接或按钮,他们将被导航到pets/id
  • 使用代码中存在的URL,我将ID附加到它,通过ID获取宠物的详细信息。详细信息页面位于文件夹pets/[id]/page.js
    您可以阅读本文以获得更清晰的概念
  • 路由基础:https://nextjs.org/docs/app/building-your-application/routing
  • 动态路线:

https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes

  • 链接和导航:

https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating

  • 服务器组件:

https://nextjs.org/docs/app/building-your-application/rendering/server-components

  • 客户端组件:

https://nextjs.org/docs/app/building-your-application/rendering/client-components

  • 何时使用服务器和客户端组件?:

https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#when-to-use-server-and-client-components

所有宠物详情页:projectName\src\app\pets\page.js

import Link from "next/link"
import LinkButton from "../comp/LinkButton"

async function GetPets() {
    let data = await fetch('https://653bf08fd5d6790f5ec7a989.mockapi.io/pets')
    let PetsData = await data.json()
    // console.log(PetsData);
    // LOGGED IN TERMINAL BCOZ ITS SERVER-SIDE

    return PetsData
}

export default async function Pets() {

    const PetsData = await GetPets()

    return (
        <div>
            <h1>All Pets !</h1>
            {
                PetsData.map((p, i) => {
                    return (
                        <div style={{
                            border: "1px solid black",
                            padding: "25px",
                            margin: '25px'
                        }}
                            key={i}
                        >
                            <img src={p.avatar} width="250" alt="" />
                            <h3>{p.name}</h3>
                            <Link style={{ color: "blue" }} href={`/pets/` + p.id}> VIew </Link>

                            <LinkButton ID={p.id} />
                        </div>
                    )
                })
            }

        </div>
    )
}

宠物详情页:projectName\src\app\pets\[id]\page.js

async function GetDetailsByID(ID) {
    let data = await fetch('https://653bf08fd5d6790f5ec7a989.mockapi.io/pets/' + ID)

    // I GOT THIS URL BY TRYING TO APPEND ID TO URL PROVIDED IN CODE

    let PetDetails = await data.json()
    // console.log(Object.keys(PetDetails));
    // LOGGED IN TERMINAL BCOZ ITS SERVER-SIDE

    return PetDetails
}

export default async function DetailsPage({ params }) {
    let Details = await GetDetailsByID(params.id)
    // AFTER GETTING ID I WILL PASS IT THE API CALL

    // THIS PAGE WILL BE SERVER RENDERED

    return (
        <div>
            <h1>Full Pet Deyails :</h1>
            <img src={Details.avatar} alt="" />
            <p className="text-gray-600">{Details.name}</p>
            <p className="text-gray-600">{Details.id}</p>
            <p className="text-gray-600">{Details.age}</p>
            <p className="text-gray-600">{Details.Gender}</p>
            <p className="text-gray-600">{Details.breed}</p>
            <p className="text-gray-600">{Details.description}</p>
            <p className="text-gray-600">{Details.createdAt}</p>



        </div>
    )
}

comp文件夹下的LinkButton.js组件projectName\src\app\comp\LinkButton.js**

'use client'
import { useRouter } from 'next/navigation'
import React from 'react'

const LinkButton = ({ ID }) => {
    const MyRouter = useRouter()

    // IF YOU WANT TO USE A BUTTON THEN IT COMES UNDER CLIENT SIDE 
    // RENDERING BECAUSE OF CLICK EVENT

    // HERE IM PASSING THE ID TO LINK & USING ROUTER TO NAVIGATE
    return (
        <button onClick={() => {
            MyRouter.push(`/pets/` + ID)
        }}>
            Button
        </button>
    )
}

export default LinkButton

而不是使用按钮,你可以样式链接标签看起来像一个按钮!

输出量:
1.后藤http://localhost:3000/pets
1.你将有一个卡片一样的布局,与链接标签命名为蓝色的视图和按钮命名为按钮。
1.点击它们,你会进入一个页面,例如第一个宠物被点击http://localhost:3000/pets/1
1.在此页面上,详细信息通过ID获取。
1.打开控制台,然后open Network Tab点击pets,然后在右手边点击预览,你会看到页面是预先呈现的!
1.类似于详细信息页面,您将在Network Tab中单击预览,您将看到页面已预渲染。

  • 评论询问任何疑问。*
  • 此代码将从myside(个人电脑)中删除。*

相关问题