skip to Main Content

So I’m trying to build a logic which will enable user to see more details about the specific product that was clicked on, but I only managed to make it appear in the URL for now. How can I achieve this?

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.jsx';
import VinylClocks from './Components/VinylClocks.jsx';
import CustomClocks from './Components/CustomClocks.jsx';
import About from './Components/About.jsx';
import Contact from './Components/Contact.jsx';
import ProductPage from './Components/ProductPage.jsx';
import './index.css';
import {
  createBrowserRouter,
  RouterProvider,
  Route,
} from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <App/>,
  },
  {
    path: "vinylclocks",
    element: <VinylClocks/>,
  },
  {
    path: "customclocks",
    element: <CustomClocks/>,
  },
  {
    path: "about",
    element: <About/>,
  },
  {
    path: "contact",
    element: <Contact/>,
  },
  {
    path: "cart",
    element: <VinylClocks/>,
  },
  {
    path: "productpage/:name",
    element: <ProductPage/>,
  },
]);

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>,
)
import React, { useEffect, useMemo, useState } from "react";
import "./VinylClocks.css";
import Navbar from "./Navbar.jsx";
import Footer from "./Footer.jsx";
import SortButton from "./SortButton.jsx";
import { data } from "./data.js";
import Product from "./Product.jsx";
import FilterButton from "./FilterButton.jsx";

export default function VinylClocks() {
  const [dataList, setDataList] = useState([]);
  const [selectedCategory, setSelectedCategory] = useState("");
  const [sortOption, setSortOption] = useState("latest");

  // Add default value on page load
  useEffect(() => {
    setDataList(data);
  }, []);

  // Function to get filtered and sorted list
  function getFilteredAndSortedList() {
    let filteredList = dataList;
    // Filter by category
    if (selectedCategory) {
      filteredList = dataList.filter((item) => item.cat === selectedCategory);
    }

    // Sort by 
    switch (sortOption) {
      case "highToLow":
        filteredList.sort((a, b) => b.price - a.price);
        break;
      case "lowToHigh":
        filteredList.sort((a, b) => a.price - b.price);
        break;
        case "oldest":
          filteredList.sort((a, b) => a.id - b.id);
        break;

      default:
        // Latest or default sorting
        case "latest":
        filteredList.sort((a, b) => b.id - a.id);
        break;
    }

    return filteredList;
  }

  // Avoid duplicate function calls with useMemo
  var filteredAndSortedList = useMemo(getFilteredAndSortedList, [
    selectedCategory,
    sortOption,
    dataList,
  ]);

  function handleCategoryChange(option) {
    setSelectedCategory(option);
  }

  function handleSortChange(option) {
    setSortOption(option);
  }

  return (
    <>
      <header className="header">
        <Navbar />
      </header>
      <div className="vc-container">
        <div className="filter-sort">
          <FilterButton onFilterChange={handleCategoryChange}/>
          <SortButton onSortChange={handleSortChange} />
        </div>
        <div className="products-container">
          <div className="catSort-container">
              <form onFilterChange={handleCategoryChange} className="cat-form" action="#">
                <h5>Categories:</h5>
                <input type="checkbox" checked={selectedCategory === ""} onChange={() => setSelectedCategory("")} id="all" className="radio-input" name="" value=""></input>
                <label htmlFor="all">All</label><br/>
                <input type="checkbox" checked={selectedCategory === "movies"} onChange={() => setSelectedCategory( "movies")} id="movies" className="radio-input" name="" value="movies"></input>
                <label htmlFor="movies">Movies</label><br/>
                <input type="checkbox" checked={selectedCategory === "music"} onChange={() => setSelectedCategory("music")} id="music" className="radio-input" name="" value="music"></input>
                <label htmlFor="music">Music</label><br/>
                <input type="checkbox" checked={selectedCategory === "sport"} onChange={() => setSelectedCategory("sport")} id="sport" className="radio-input" name="" value="sport"></input>
                <label htmlFor="sport">Sport</label><br/>
                <input type="checkbox" checked={selectedCategory === "other"} onChange={() => setSelectedCategory("other")} id="other" className="radio-input" name="" value="other"></input>
                <label htmlFor="other">Other</label>
            </form>
            <form onSortChange={handleSortChange} className="sort-form" action="#">
                <h5>Sort by:</h5>
                <h3>Date:</h3>
                <input type="checkbox" checked={sortOption === "latest"} onChange={() => setSortOption("latest")}  
                       id="latest" className="radio-input" name="" value="latest"></input>
                <label>Latest</label><br/>
                <input type="checkbox" checked={sortOption === "oldest"} onChange={() => setSortOption( "oldest")} 
                       id="oldest" className="radio-input" name="" value="oldest"></input>
                <label>Oldest</label><br/>
                <h3>Price:</h3>
                <input type="checkbox" checked={sortOption === "highToLow"} onChange={() => setSortOption("highToLow")} 
                       id="lowest" className="radio-input" name="" value="highToLow"></input>
                <label>Highest</label><br/>
                <input type="checkbox" checked={sortOption === "lowToHigh"} onChange={() => setSortOption( "lowToHigh")} 
                       id="highest" className="radio-input" name="" value="lowToHigh"></input>
                <label>Lowest</label>
                
            </form>
          </div>
            <div className="products">
              {filteredAndSortedList.map((item, id) => (
                <Product {...item} key={id} />
              ))}
              </div>
        </div>
      </div>
      <Footer />
    </>
  );
}
import React from "react";
import "./VinylClocks.css";
import { Link } from "react-router-dom";

export default function Product({name, price, img}) {
    return (

            <div className="products-card">
                <div className="name-price-tag">
                <Link to={`/productpage/${name}`}><img src={img}/></Link>
                <div className="price-container">
                    <p className="product-name">{name}</p>
                    <span className="price">${price}</span>
                </div>
            </div>   
            </div>
    )        
}
import React from "react";
import "./ProductPage.css";
import { data } from "./data.js";
 

export default function ProductPage() {

    return (

           <>
            {data.map((element, id) => (
            <div className="productPage-container" key={id}>

                <div className="image-container">
                    <img src={element.img} {...element}/>
                </div>
                <div className="about-product">
                    <span className="product-type">{element.type}</span>
                    <h2 className="product-name">{element.name}</h2>
                    <span className="product-price">{element.price}</span>
                    <p className="product-desc">{element.desc}</p>
                </div>
            </div>
            ))}
           </>
    )        
}

p.s. i’m aware that ProductPage is just mapping the array all over again, that ‘s what i’m trying to figure out.

2

Answers


  1. You need to filter the product details based on the product name provided in the URL.
    In ProductPage,

    • Extract the product name from the URL parameters.
      const location = useLocation();
      const productName = location.pathname.split("/").pop();
    

    Use the useLocation hook from react-router-dom to access the current location. Extract the product name from the URL parameters using location.pathname.split("/").pop().

    • Find the product in your data array that matches the extracted product name.
    const product = data.find((element) => element.name === productName);
    

    Use the find method to get the product from the data array that matches the extracted product name.

    • Handle the case where the product is not found
    if (!product) {
        return <div>Product not found</div>;
      }
    

    If the product is not found, display a message like "Product not found."

    • Details of the matched product.
    return (
        <div className="productPage-container">
          <div className="image-container">
            <img src={product.img} alt={product.name} />
          </div>
          <div className="about-product">
            <span className="product-type">{product.type}</span>
            <h2 className="product-name">{product.name}</h2>
            <span className="product-price">${product.price}</span>
            <p className="product-desc">{product.desc}</p>
          </div>
        </div>
      );
    
    Login or Signup to reply.
  2. Use the useParams hook to access the product’s name value from the route parameters.

    {
      path: "productpage/:name",
      element: <ProductPage/>,
    },
    

    Use the current name parameter to search the data array for a matching element by name property. Don’t forget to account for missing data.

    import React from "react";
    import "./ProductPage.css";
    import { useParams } from 'react-router-dom';
    import { data } from "./data.js";
     
    export default function ProductPage() {
      const { name } = useParams();
    
      const item = data.find(item => item.name === name);
    
      if (!item) {
        return <div>No item</div>;
      }
    
      return (
        <div className="productPage-container" key={id}>
          <div className="image-container">
            <img src={item.img} {...element}/>
          </div>
          <div className="about-product">
            <span className="product-type">{item.type}</span>
            <h2 className="product-name">{item.name}</h2>
            <span className="product-price">{item.price}</span>
          <p className="product-desc">{item.desc}</p>
        </div>
      );    
    }
    

    For details see:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search