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

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

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

  1. export const draft = [
  2. {
  3. id: 1,
  4. title: "Burkina Faso serve Togo Vincent student",
  5. imageUrl: "/cards/1.jpg",
  6. imageType: "single image",
  7. price: 8000,
  8. buttonText: "View Design",
  9. cardType: "Single Page",
  10. popularity: 1,
  11. cardCategory: "singlePageCard",
  12. },
  13. ];
  14. export default draft;

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

  1. import Cards from "../../components/Cards/Cards";
  2. import { draft } from "../../Data/Draft_Data";
  3. const ExperimentalCard = () => {
  4. return (
  5. <div className="ml-[1rem] md:ml-14">
  6. <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-10 min-h-[120vh]">
  7. {draft.map((item, index) => (
  8. <Cards key={index} items={item} />
  9. ))}
  10. </div>
  11. </div>
  12. );
  13. };
  14. export default ExperimentalCard;

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

Cards.jsx

  1. import { useRouter } from 'next/navigation';
  2. import React from "react";
  3. const Cards = ({ items }) => {
  4. const router = useRouter();
  5. const handleCardClick = (id) => {
  6. router.push(`/experimental/${id}`);
  7. };
  8. return (
  9. <div>
  10. <div className="mx-5 lg:mx-10">
  11. <div
  12. className="w-full h-[30rem] md:h-[25rem] lg:h-[20rem] items-center bg-contain bg-no-repeat"
  13. style={{ backgroundImage: `url('${items.imageUrl}')` }}
  14. onClick={() => handleCardClick(item.id)}
  15. >
  16. <div className="bg-[#23272a93] relative z-0 w-32 mb-4 ml-4 h-11 text-center items-center flex rounded-sm justify-center ">
  17. <p className="text-base-100 uppercase">{items.cardType}</p>
  18. </div>
  19. </div>
  20. <div className="flex flex-row mt-4 justify-between">
  21. <h2 className="font-normal text-[1.5rem] md:text-[1.4rem] lg:text-xl basis-2/3">
  22. {items.title}
  23. </h2>
  24. <p className="font-bold text-2xl lg:text-xl basis-1/3 text-right md:text-left lg:text-right">
  25. {items.price}
  26. </p>
  27. </div>
  28. </div>
  29. </div>
  30. );
  31. };
  32. export default Cards;

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

[id]/page.jsx

  1. import { useRouter } from 'next/navigation';
  2. import React from 'react';
  3. const Page = () => {
  4. const router = useRouter();
  5. const { id } = router.query;
  6. return (
  7. <div>
  8. <h1>Experimental Card Details</h1>
  9. <p>Card ID: {id}</p>
  10. <p>Card title: {title}</p>
  11. <p>Card imageUrl: {imageUrl}</p>
  12. <p>Card imageType: {imageType}</p>
  13. <p>Card price: {price}</p>
  14. <p>Card buttonText: {buttonText}</p>
  15. <p>Card cardType: {cardType}</p>
  16. <p>Card popularity: {popularity}</p>
  17. <p>Card cardCategory: {cardCategory}</p>
  18. </div>
  19. );
  20. };
  21. 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

  1. export const draft = [
  2. {
  3. id: 1,
  4. title: &quot;Burkina Faso serve Togo Vincent student&quot;,
  5. imageUrl: &quot;/cards/1.jpg&quot;,
  6. imageType: &quot;single image&quot;,
  7. price: 8000,
  8. buttonText: &quot;View Design&quot;,
  9. cardType: &quot;Single Page&quot;,
  10. popularity: 1,
  11. cardCategory: &quot;singlePageCard&quot;,
  12. },
  13. ];
  14. export default draft;

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

  1. import Cards from &quot;../../components/Cards/Cards&quot;;
  2. import { draft } from &quot;../../Data/Draft_Data&quot;;
  3. const ExperimentalCard = () =&gt; {
  4. return (
  5. &lt;div className=&quot;ml-[1rem] md:ml-14&quot;&gt;
  6. &lt;div className=&quot;grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-y-10 min-h-[120vh]&quot;&gt;
  7. {draft.map((item, index) =&gt; (
  8. &lt;Cards key={index} items={item} /&gt;
  9. ))}
  10. &lt;/div&gt;
  11. &lt;/div&gt;
  12. );
  13. };
  14. 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

  1. &#39;use client&#39;
  2. import { useRouter } from &#39;next/navigation&#39;
  3. import React from &quot;react&quot;;
  4. const Cards = ({ items }) =&gt; {
  5. const router = useRouter()
  6. const handleCardClick = (id) =&gt; {
  7. router.push(`/experimental/${id}`);
  8. };
  9. return (
  10. &lt;div&gt;
  11. &lt;div className=&quot;mx-5 lg:mx-10&quot;&gt;
  12. &lt;div
  13. className=&quot;w-full h-[30rem] md:h-[25rem] lg:h-[20rem] items-center bg-contain bg-no-repeat&quot;
  14. style={{ backgroundImage: `url(&#39;${items.imageUrl}&#39;)` }}
  15. onClick={() =&gt; handleCardClick(item.id)}
  16. &gt;
  17. &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;
  18. &lt;p className=&quot;text-base-100 uppercase&quot;&gt;{items.cardType}&lt;/p&gt;
  19. &lt;/div&gt;
  20. &lt;/div&gt;
  21. &lt;div className=&quot;flex flex-row mt-4 justify-between&quot;&gt;
  22. &lt;h2 className=&quot;font-normal text-[1.5rem] md:text-[1.4rem] lg:text-xl basis-2/3&quot;&gt;
  23. {items.title}
  24. &lt;/h2&gt;
  25. &lt;p className=&quot;font-bold text-2xl lg:text-xl basis-1/3 text-right md:text-left lg:text-right&quot;&gt;
  26. ৳{items.price}
  27. &lt;/p&gt;
  28. &lt;/div&gt;
  29. {/* &lt;p&gt;Popularity: {items.popularity}&lt;/p&gt; */}
  30. &lt;/div&gt;
  31. &lt;/div&gt;
  32. );
  33. };
  34. 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

  1. &#39;use client&#39;
  2. import { useRouter } from &#39;next/navigation&#39;
  3. import React from &#39;react&#39;
  4. const Page = () =&gt; {
  5. const router = useRouter();
  6. const { id } = router.query;
  7. return (
  8. &lt;div&gt;
  9. &lt;h1&gt;Experimental Card Details&lt;/h1&gt;
  10. &lt;p&gt;Card ID: {id}&lt;/p&gt;
  11. &lt;p&gt;Card title: {title}&lt;/p&gt;
  12. &lt;p&gt;Card imageUrl: {imageUrl}&lt;/p&gt;
  13. &lt;p&gt;Card imageType: {imageType}&lt;/p&gt;
  14. &lt;p&gt;Card price: {price}&lt;/p&gt;
  15. &lt;p&gt;Card buttonText: {buttonText}&lt;/p&gt;
  16. &lt;p&gt;Card cardType: {cardType}&lt;/p&gt;
  17. &lt;p&gt;Card popularity: {popularity}&lt;/p&gt;
  18. &lt;p&gt;Card cardCategory: {cardCategory}&lt;/p&gt;
  19. &lt;/div&gt;
  20. );
  21. }
  22. export default Page

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

  1. src\app\experimental\[id]\page.jsx (7:10) @ id
  2. 5 | const Page = () =&gt; {
  3. 6 | const router = useRouter();
  4. &gt; 7 | const { id } = router.query;
  5. | ^
  6. 8 |
  7. 9 | return (
  8. 10 | &lt;div&gt;

答案1

得分: 1

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

你的情况

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

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

TypeScript:

  1. export default async function Page({
  2. // 动态路由参数
  3. params,
  4. searchParams,
  5. }: {
  6. // 在您的情况下是[id]
  7. params: { id: string };
  8. searchParams: { ref: string };
  9. })

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

您的实现应该如下所示

  1. // 请注意,这将是一个RSC,因此不需要'use client'指令
  2. import React from 'react';
  3. const Page = ({ params }) => {
  4. const id = params.id;
  5. return (
  6. <div>
  7. <h1>Experimental Card Details</h1>
  8. <p>Card ID: {id}</p>
  9. </div>
  10. );
  11. }
  12. export default Page
英文:

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

your case

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

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

typescript:

  1. export default async function Page({
  2. // dynamic route params
  3. params,
  4. searchParams,
  5. }: {
  6. // [id] in your case
  7. params: { id: string };
  8. searchParams: { ref: string };
  9. })

Check the NextJs documentation for details

You implementation should be like this

  1. // note that this will be a RSC, therefore no need for &#39;use client&#39; directive
  2. import React from &#39;react&#39;
  3. const Page = ({ params }) =&gt; {
  4. const id = params.id
  5. return (
  6. &lt;div&gt;
  7. &lt;h1&gt;Experimental Card Details&lt;/h1&gt;
  8. &lt;p&gt;Card ID: {id}&lt;/p&gt;
  9. &lt;/div&gt;
  10. );
  11. }
  12. export default Page

答案2

得分: 1

  1. `next/navigation` 中,`router` 不支持 `query` 参数。请改用 `useParams`
  2. 调用方式:
  3. ```jsx
  4. <Link href={"/experimental/123"}>
  5. button
  6. </Link>

接收方式:

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

另请参考:

  1. https://stackoverflow.com/a/76609568/13431819
  2. https://stackoverflow.com/a/76613628/13431819
  1. <details>
  2. <summary>英文:</summary>
  3. `router` in `next/navigation` doesn&#39;t support `query` parameter. Use `useParams` instead.
  4. Invoke as

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

  1. Receive as

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

  1. Also refer
  2. 1. https://stackoverflow.com/a/76609568/13431819
  3. 2. https://stackoverflow.com/a/76613628/13431819
  4. </details>
  5. # 答案3
  6. **得分**: 1
  7. I solved it with **useParams** in
  8. **"[id]/page.jsx"** -> 组件,
  9. **"experimental/${id}"** -> 路由
  10. I just get the id from the Route then perform find operation in my local json to get the single card data.
  11. Here is my Dynamic Route Code for **[id]/page.jsx**
  12. ```jsx
  13. "use client";
  14. import React from "react";
  15. import { draft } from "../../../Data/Draft_Data";
  16. import { useParams } from "next/navigation";
  17. const Page = () => {
  18. const params = useParams();
  19. const card = draft.find((item) => item.id === parseInt(params.id));
  20. return (
  21. <div>
  22. <h1>Experimental Card Details</h1>
  23. {card ? (
  24. <>
  25. <p>Card ID: {card.id}</p>
  26. <p>Card title: {card.title}</p>
  27. </>
  28. ) : (
  29. <p>Card not found.</p>
  30. )}
  31. </div>
  32. );
  33. };
  34. 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

  1. &quot;use client&quot;;
  2. import React from &quot;react&quot;;
  3. import { draft } from &quot;../../../Data/Draft_Data&quot;;
  4. import { useParams } from &quot;next/navigation&quot;;
  5. const Page = () =&gt; {
  6. const params = useParams();
  7. const card = draft.find((item) =&gt; item.id === parseInt(params.id));
  8. return (
  9. &lt;div&gt;
  10. &lt;h1&gt;Experimental Card Details&lt;/h1&gt;
  11. {card ? (
  12. &lt;&gt;
  13. &lt;p&gt;Card ID: {card.id}&lt;/p&gt;
  14. &lt;p&gt;Card title: {card.title}&lt;/p&gt;
  15. &lt;/&gt;
  16. ) : (
  17. &lt;p&gt;Card not found.&lt;/p&gt;
  18. )}
  19. &lt;/div&gt;
  20. );
  21. };
  22. 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:

确定