Search code examples
javascriptreactjswebnext.js

How can I pass an {id} property to my Next.js dynamic route using Context API?


I have a problem with passing the ${id} property to my dynamic route [id]>page.jsx, which is inside the CartItemPage.jsx file. I'm using the Context API, similar to React, where I store an array of CartItems and render my Cart with this array. I have a home page and a catalog page, and there are ProductItem components. When I click on them, I need to navigate the user to CartItemPage[id] of that specific product, but I'm having trouble getting the id property.

Here is the code for my CartItem component (actually a product):

'use client';
import Link from 'next/link';
import styles from './CartItem.module.css';
import { useState, useEffect } from 'react';
import { useAppStore } from '../../app/Context/store';

const CartItem = ({ data }) => {
    const [addedToCart, setAddedToCart] = useState(false);
    const { addToCart, cartItems } = useAppStore();

    useEffect(() => {
        if (cartItems.some(cartItem => cartItem.id === data.id)) {
            setAddedToCart(true);
        } else {
            setAddedToCart(false);
        }
    }, [cartItems]);

    const handleAddToCart = data => {
        if (cartItems.some(cartItem => cartItem.title === data.title)) {
            setAddedToCart(true);
        } else {
            addToCart(data);
            setAddedToCart(true);
            console.log(data);
            console.log(cartItems);
        }
    };

    return (
        <>
            <div className={styles.productCard}>
                <Link href={`/cartItemPage/${data.id}`}>
                    <div className='flex items-center flex-col'>
                        <img className={styles.productImage} src={data.image} alt={data.title} />
                        <h3 className={styles.productTitle}>{data.title}</h3>
                        <p className={styles.productPrice}>{data.price} $</p>

                        {/* Додаткові деталі */}
                    </div>
                </Link>
                <button
                    onClick={() => {
                        handleAddToCart(data);
                    }}
                    className={addedToCart ? styles.addedButton : styles.addButton}
                >
                    {addedToCart ? 'У кошику' : 'До кошику'}
                </button>
            </div>
        </>
    );
};

export default CartItem;

here is a code of CartItemPage, where i created [id] > page.jsx:

'use client';
import React, { useEffect, useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { useAppStore } from '@/app/Context/store';

const CartItemPage = ({ id }) => {
    const router = useRouter();
    const searchParams = useSearchParams();
    const { addToCart, cartItems } = useAppStore();
    const [cartItem, setCartItem] = useState(null);

    useEffect(() => {
        const fetchCartItem = async () => {
            try {
                const response = await fetch(`https://fakestoreapi.com/products/${id}`);
                const data = await response.json(response.data);
                setCartItem(data);
            } catch (error) {
                console.log(error);
            }
        };

        if (id) {
            fetchCartItem();
        }
    }, [id]);

    return (
        <>
            <div>id: {id}</div>
        </>
    );
};

export default CartItemPage;

Solution

  • Hey there!

    You simply have to rename the id parameter to params and if you want to refer to the id just use params.id.

    Like here is your updated code for CartItemPage.jsx:

    Edit

    Also make sure that the page.js file for your CartItemPage is inside a directory called [id]. So the file structure should be cart > [id] > page.js.

    "use client";
    import React, { useEffect, useState } from "react";
    import { useRouter, useSearchParams } from "next/navigation";
    import { useAppStore } from "@/app/Context/store";
    
    const CartItemPage = ({ params }) => {
      const router = useRouter();
      const searchParams = useSearchParams();
      const { addToCart, cartItems } = useAppStore();
      const [cartItem, setCartItem] = useState(null);
    
      useEffect(() => {
        const fetchCartItem = async () => {
          try {
            const response = await fetch(`https://fakestoreapi.com/products/${id}`);
            const data = await response.json(response.data);
            setCartItem(data);
          } catch (error) {
            console.log(error);
          }
        };
    
        if (params.id) {
          fetchCartItem();
        }
      }, [params]);
    
      return (
        <>
          <div>id: {params.id}</div>
        </>
      );
    };
    
    export default CartItemPage;