将数据从一个页面传递到Next.js 13中的动态路由,使用应用程序路由器。

huangapple go评论69阅读模式
英文:

Passing data from one page to a dynamic route in Next.js 13 with app router

问题

在NextJS 13中使用应用程序路由器(app router),我想从"/experimental"传递数据到动态路由"/experimental/${id}"。但是它给我"router.query"作为未定义。是否有更好的方法?

我尝试在NextJS 13中使用"next/navigation",但无法将数据传递给另一个组件。

以下是我的JSON数据:

draft.js

export const draft = [
  {
    id: 1,
    title: "Burkina Faso serve Togo Vincent student",
    imageUrl: "/cards/1.jpg",
    imageType: "single image",
    price: 8000,
    buttonText: "View Design",
    cardType: "Single Page",
    popularity: 1,
    cardCategory: "singlePageCard",
  },
];

export default draft;

这是我的ExperimentCard组件,我在其中传递并映射Draft.js数据对象:

import Cards from "../../components/Cards/Cards";
import { draft } from "../../Data/Draft_Data";

const ExperimentalCard = () => {
  return (
    <div className="ml-[1rem] md:ml-14">
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-10 min-h-[120vh]">
        {draft.map((item, index) => (
          <Cards key={index} items={item} />
        ))}
      </div>
    </div>
  );
};

export default ExperimentalCard;

Card组件将如下所示。从Cards组件中,我想要将数据传递到动态路由"/experimental/${id}"。

Cards.jsx

import { useRouter } from 'next/navigation';
import React from "react";

const Cards = ({ items }) => {
  const router = useRouter();

  const handleCardClick = (id) => {
    router.push(`/experimental/${id}`);
  };

  return (
    <div>
      <div className="mx-5  lg:mx-10">
        <div
          className="w-full h-[30rem] md:h-[25rem]  lg:h-[20rem] items-center bg-contain bg-no-repeat"
          style={{ backgroundImage: `url('${items.imageUrl}')` }}
          onClick={() => handleCardClick(item.id)}
        >
          <div className="bg-[#23272a93] relative z-0 w-32 mb-4 ml-4 h-11 text-center items-center flex rounded-sm justify-center ">
            <p className="text-base-100 uppercase">{items.cardType}</p>
          </div>
        </div>
        <div className="flex flex-row mt-4 justify-between">
          <h2 className="font-normal text-[1.5rem] md:text-[1.4rem] lg:text-xl basis-2/3">
            {items.title}
          </h2>
          <p className="font-bold text-2xl lg:text-xl basis-1/3 text-right md:text-left lg:text-right">
            {items.price}
          </p>
        </div>
      </div>
    </div>
  );
};

export default Cards;

当我点击组件时,它将导航到动态链接"/experimental/${id}"。但是它给我一个错误:

[id]/page.jsx

import { useRouter } from 'next/navigation';
import React from 'react';

const Page = () => {
  const router = useRouter();
  const { id } = router.query;

  return (
    <div>
      <h1>Experimental Card Details</h1>
      <p>Card ID: {id}</p>
      <p>Card title: {title}</p>
      <p>Card imageUrl: {imageUrl}</p>
      <p>Card imageType: {imageType}</p>
      <p>Card price: {price}</p>
      <p>Card buttonText: {buttonText}</p>
      <p>Card cardType: {cardType}</p>
      <p>Card popularity: {popularity}</p>
      <p>Card cardCategory: {cardCategory}</p>
    </div>
  );
};

export default Page;

未处理的运行时错误 TypeError: 无法解构"router.query"的属性'id',因为它未定义。

希望这可以帮助您解决问题。

英文:

Problem Statement: In NextJS 13 with app router, I want to pass data from "/experimental" to dynamic route "/experimental/${id}". It gives me 'router.query' as it is undefined. Is there any better approach?

I tried using 'next/navigation' in the nextjs 13 with app router. I can't pass the data to one component to another.

Here is my Json data

draft.js

export const draft = [
  {
    id: 1,
    title: &quot;Burkina Faso serve Togo Vincent student&quot;,
    imageUrl: &quot;/cards/1.jpg&quot;,
    imageType: &quot;single image&quot;,
    price: 8000,
    buttonText: &quot;View Design&quot;,
    cardType: &quot;Single Page&quot;,
    popularity: 1,
    cardCategory: &quot;singlePageCard&quot;,
  },
];

export default draft;

Here is my ExperimentCard where I pass and mapping the Draft.js data object

import Cards from &quot;../../components/Cards/Cards&quot;;
import { draft } from &quot;../../Data/Draft_Data&quot;;

const ExperimentalCard = () =&gt; {
  return (
    &lt;div className=&quot;ml-[1rem] md:ml-14&quot;&gt;
      &lt;div className=&quot;grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-10 min-h-[120vh]&quot;&gt;
        {draft.map((item, index) =&gt; (
          &lt;Cards key={index} items={item} /&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  );
};

export default ExperimentalCard;

And the Card components will like this. And From Cards Components I want to pass data to dynamic route "/experimental/${id}".

Cards.jsx

&#39;use client&#39;
 
import { useRouter } from &#39;next/navigation&#39;
import React from &quot;react&quot;;

const Cards = ({ items }) =&gt; {

  const router = useRouter()
  
  const handleCardClick = (id) =&gt; {
    router.push(`/experimental/${id}`);
  };

  return (
    &lt;div&gt;
      
        &lt;div className=&quot;mx-5  lg:mx-10&quot;&gt;
          &lt;div
            className=&quot;w-full h-[30rem] md:h-[25rem]  lg:h-[20rem] items-center bg-contain bg-no-repeat&quot;
            style={{ backgroundImage: `url(&#39;${items.imageUrl}&#39;)` }}
            onClick={() =&gt; handleCardClick(item.id)}
          &gt;
            &lt;div className=&quot;bg-[#23272a93] relative z-0 w-32 mb-4 ml-4 h-11 text-center items-center flex rounded-sm justify-center &quot;&gt;
              &lt;p className=&quot;text-base-100 uppercase&quot;&gt;{items.cardType}&lt;/p&gt;
            &lt;/div&gt;
          &lt;/div&gt;
          &lt;div className=&quot;flex flex-row mt-4 justify-between&quot;&gt;
            &lt;h2 className=&quot;font-normal text-[1.5rem] md:text-[1.4rem] lg:text-xl basis-2/3&quot;&gt;
              {items.title}
            &lt;/h2&gt;
            &lt;p className=&quot;font-bold text-2xl lg:text-xl basis-1/3 text-right md:text-left lg:text-right&quot;&gt;
            ৳{items.price}
            &lt;/p&gt;
          &lt;/div&gt;
          {/* &lt;p&gt;Popularity: {items.popularity}&lt;/p&gt; */}
        &lt;/div&gt;
   
    &lt;/div&gt;
  );
};

export default Cards;

When I click the component it will navigate to the dynamic link "/experimental/${id}". It gives me an error

[id]/page.jsx

&#39;use client&#39;
import { useRouter } from &#39;next/navigation&#39;
import React from &#39;react&#39;

const Page = () =&gt; {
  const router = useRouter();
  const { id } = router.query; 

  return (
    &lt;div&gt;
      &lt;h1&gt;Experimental Card Details&lt;/h1&gt;
      &lt;p&gt;Card ID: {id}&lt;/p&gt;
      &lt;p&gt;Card title: {title}&lt;/p&gt;
      &lt;p&gt;Card imageUrl: {imageUrl}&lt;/p&gt;
      &lt;p&gt;Card imageType: {imageType}&lt;/p&gt;
      &lt;p&gt;Card price: {price}&lt;/p&gt;
      &lt;p&gt;Card buttonText: {buttonText}&lt;/p&gt;
      &lt;p&gt;Card cardType: {cardType}&lt;/p&gt;
      &lt;p&gt;Card popularity: {popularity}&lt;/p&gt;
      &lt;p&gt;Card cardCategory: {cardCategory}&lt;/p&gt;
    &lt;/div&gt;
  );
}

export default Page

Unhandled Runtime Error TypeError: Cannot destructure property 'id' of 'router.query' as it is undefined.

src\app\experimental\[id]\page.jsx (7:10) @ id

   5 | const Page = () =&gt; {
   6 | const router = useRouter();
&gt;  7 | const { id } = router.query; 
     |        ^
   8 | 
   9 | return (
  10 |   &lt;div&gt;

答案1

得分: 1

这是我在应用程序路由器中处理参数和查询的方式

你的情况

export default async function Page({
  // 在这种情况下,您的动态值是[id]
  params 
})

如果您有searchParams,例如[id]?ref=foo-bar

TypeScript:

export default async function Page({
  // 动态路由参数
  params,
  searchParams,
}: {
  // 在您的情况下是[id]
  params: { id: string };
  searchParams: { ref: string };
})

请查看Next.js文档以获取详细信息

您的实现应该如下所示

// 请注意,这将是一个RSC,因此不需要'use client'指令
import React from 'react';

const Page = ({ params }) => {
  const id = params.id;

  return (
    <div>
      <h1>Experimental Card Details</h1>
      <p>Card ID: {id}</p>
    </div>
  );
}

export default Page
英文:

This is how I handle params and queries in the App router

your case

export default async function Page({
  // your dynamic value in this case [id]
  params 
})

In case you have searchParams eg [id]?ref=foo-bar

typescript:

export default async function Page({
  // dynamic route params
  params,
  searchParams,
}: {
  // [id] in your case
  params: { id: string };
  searchParams: { ref: string };
})

Check the NextJs documentation for details

You implementation should be like this

// note that this will be a RSC, therefore no need for &#39;use client&#39; directive
import React from &#39;react&#39;

const Page = ({ params }) =&gt; {
  const id = params.id 

  return (
    &lt;div&gt;
      &lt;h1&gt;Experimental Card Details&lt;/h1&gt;
      &lt;p&gt;Card ID: {id}&lt;/p&gt;
    &lt;/div&gt;
  );
}

export default Page

答案2

得分: 1

在 `next/navigation` 中,`router` 不支持 `query` 参数。请改用 `useParams`。

调用方式:
```jsx
<Link href={"/experimental/123"}>
	button
</Link>

接收方式:

export default function Page({ params }: { params: { id: string } }) {
	return <h1>{params.id}</h1>;
}

另请参考:

  1. https://stackoverflow.com/a/76609568/13431819
  2. https://stackoverflow.com/a/76613628/13431819

<details>
<summary>英文:</summary>

`router` in `next/navigation` doesn&#39;t support `query` parameter. Use `useParams` instead.

Invoke as

<Link href={"/experimental/123"}>
button
</Link>


Receive as

export default function Page({ params }: { params: { id: string } }) {
return <h1>{params.id}</h1>;
}


Also refer
1. https://stackoverflow.com/a/76609568/13431819
2. https://stackoverflow.com/a/76613628/13431819

</details>



# 答案3
**得分**: 1

I solved it with **useParams** in 

**"[id]/page.jsx"** -> 组件,   
**"experimental/${id}"** -> 路由

I just get the id from the Route then perform find operation in my local json to get the single card data.

Here is my Dynamic Route Code for **[id]/page.jsx**

```jsx
"use client";

import React from "react";
import { draft } from "../../../Data/Draft_Data";
import { useParams } from "next/navigation";

const Page = () => {
  const params = useParams();
  const card = draft.find((item) => item.id === parseInt(params.id));

  return (
    <div>
      <h1>Experimental Card Details</h1>
      {card ? (
        <>
          <p>Card ID: {card.id}</p>
          <p>Card title: {card.title}</p>
        </>
      ) : (
        <p>Card not found.</p>
      )}
    </div>
  );
};

export default Page;
英文:

I solved it with useParams in

"[id]/page.jsx" -> component,
"experimental/${id}" -> route

I just get the id from the Route then perform find operation in my local json to get the single card data.

Here is my Dynamic Route Code for [id]/page.jsx

&quot;use client&quot;;

import React from &quot;react&quot;;
import { draft } from &quot;../../../Data/Draft_Data&quot;;
import { useParams } from &quot;next/navigation&quot;;

const Page = () =&gt; {
  const params = useParams();
  const card = draft.find((item) =&gt; item.id === parseInt(params.id));

  return (
    &lt;div&gt;
      &lt;h1&gt;Experimental Card Details&lt;/h1&gt;
      {card ? (
        &lt;&gt;
          &lt;p&gt;Card ID: {card.id}&lt;/p&gt;
          &lt;p&gt;Card title: {card.title}&lt;/p&gt;
        &lt;/&gt;
      ) : (
        &lt;p&gt;Card not found.&lt;/p&gt;
      )}
    &lt;/div&gt;
  );
};

export default Page;

huangapple
  • 本文由 发表于 2023年7月12日 23:54:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76672436.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定