-1

I am currently working on a react/typescript web shop and I have a problem. I have a JSON file that contains all product information and I have two components(pages) Home and Product. On the Home page I imported a JSON file with products and with the help of the map method I created each product in the form of a link element, each link leads to a Product component that contains product details. I have 8 products, I could create eight different pages and each product has its page, but I would prefer to have one page for all products, with eight products, it is not terrible to have 8 different pages, but imagine there are 1000 products, is it possible to on click on different products on the home page, the content on the page with product details (Product component) changes dynamically.

These are my items.JSON:

[{
"id": 1,
"name": "Earphones",
"price": 49,
"imgUrl": "/images/earphones1.webp"},
{
"id": 2,
"name": "Earphones 2",
"price": 69,
"imgUrl": "/imgs/earphones2.webp"},
{
"id": 3,
"name": "Earphones 3",
"price": 59,
"imgUrl": "/imgs/earphones3.webp"},
{
"id": 4,
"name": "Earphones 4",
"price": 79,
"imgUrl": "/imgs/earphones4.webp"},
{
"id": 5,
"name": "Earphones 5",
"price": 79,
"imgUrl": "/imgs/earphones5.webp"},
{
"id": 6,
"name": "Speaker",
"price": 89,
"imgUrl": "/imgs/speaker.webp"},
{
"id": 7,
"name": "Watch",
"price": 199,
"imgUrl": "/imgs/watch.webp"},
{
"id": 8,
"name": "Watch2",
"price": 299,
"imgUrl": "/imgs/watch2.webp"}]

This is my Home.tsx:

import items from '../data/items.json'
import "../style/style.css"
import { Link } from 'react-router-dom';

export function Home(){
return (
  <div>
    <div
      style={{
        display: "flex",
        flexWrap: "wrap",
        justifyContent: "center",
        gap: "20px",
      }}
    >
      {items.map((item) => (
        <Link
          key={item.id}
          style={{
            textDecoration: "none",
            color: "black",
          }}
          to={"/product"}
        >
          <div className="product-container">
            <div
              style={{
                backgroundColor: "#e9ecef",
                borderRadius: "20px",
                padding: "10px",
              }}
            >
            
            <img src={item.imgUrl} style={{}} width="250px" alt="" />
          </div>
          <div
            style={{
              display: "flex",
              flexDirection: "column",
              paddingInline: "20px",
              fontFamily: "fantasy",
              fontSize: "18px",
              fontWeight: "lighter",
            }}
          >
            <p style={{ color: "gray" }}>{item.name}</p>
            <p
              style={{
                transform: "translateY(-30px)",
                fontWeight: "bolder",
                fontFamily: "cursive",
              }}
            >
              ${item.price}
            </p>
          </div>
        </div>
      </Link>
    ))}
  </div>
</div>

); }

And this is my Product.tsx:

import items from '../../data/items.json'
import '../../style/style.css'
import {
  AiFillStar,
  AiOutlineStar,
  AiOutlineMinus,
  AiOutlinePlus,
} from "react-icons/ai";

export function Product(){
  return (
    <div style={{ display: "grid", placeContent: "center" }}>
      <div
        style={{
          display: "flex",
          flexWrap: "wrap",
          gap: "20px",
        }}
      >
        <div
          className="product-details-container"
          style={{
            display: "flex",
            fontFamily: "monospace",
            flexDirection: "column",
            fontSize: "25px",
            padding: "10px",
            borderRadius: "10px",
          }}
        >
          <img src={items[0].imgUrl} width="300px" alt="" />
        </div>
        <div style={{display: 'flex', flexDirection: 'column'}}>
          <p
            style={{
              fontFamily: "monospace",
              width: "300px",
              textAlign: "left",
              fontSize: "20px",
              color: "#22223b",
            }}
          >
            {items[0].name}
          </p>
          <div
            style={{ color: "#ba181b", display: "flex", alignItems: "center" }}
          >
            <AiFillStar />
            <AiFillStar />
            <AiFillStar />
            <AiFillStar />
            <AiOutlineStar />
            <p style={{ marginLeft: "5px", color: "#22223b" }}>(20)</p>
          </div>
          <p style={{fontFamily: 'monospace', fontSize: '20px'}}>${items[0].price}</p>
          <div
            style={{
              fontFamily: "monospace",
              color: "#22223b",
              fontSize: "17px",
            }}
          >
            <p>Details:</p>
            <p>Cool headphones, amazing sound.</p>
          </div>
          <div
            style={{
              display: "flex",
              alignItems: "center",
              fontFamily: "monospace",
              fontSize: "16px",
            }}
          >
            <p style={{ marginRight: "20px" }}>Quantity:</p>
            <button
              style={{
                background: "transparent",
                border: "1px solid grey",
                display: "grid",
                placeContent: "center",
                paddingInline: "20px",
                height: "50px",
              }}
            >
              <AiOutlineMinus />
            </button>
            <p
              style={{
               background: "transparent",
            border: "1px solid grey",
            display: "grid",
            placeContent: "center",
            paddingInline: "15px",
            height: "48px",
          }}
        >
          0
        </p>
        <button
          style={{
            background: "transparent",
            border: "1px solid grey",
            display: "grid",
            placeContent: "center",
            paddingInline: "20px",
            height: "50px",
          }}
        >
          <AiOutlinePlus />
        </button>
      </div>
      <button
        style={{
          background: "transparent",
          border: "1px solid darkred",
          color: "darkred",
          padding: '10px',
          fontFamily: 'monospace',
          fontSize: '17px',
          width: '150px',
          alignSelf: 'center'
        }}
      >
        Add to Cart
      </button>
    </div>
  </div>
</div>
  );
}

In product component, all product details i got from the same JSON.

Rohan Tomar
  • 427
  • 4
  • 13

1 Answers1

0

This is not a good approach to pass data from one route to other. See this link.

Anyway, I make a runnable code for you that will pass one Item object to Home page to Product page.

import { Link } from 'react-router-dom'

export interface Item {
  id: number
  name: string
  price: number
  imgUrl: string
}

const items: Item[] = [
  {
    id: 1,
    name: 'Earphones',
    price: 49,
    imgUrl: '/images/earphones1.webp',
  },
  {
    id: 2,
    name: 'Earphones 2',
    price: 69,
    imgUrl: '/imgs/earphones2.webp',
  },
  {
    id: 3,
    name: 'Earphones 3',
    price: 59,
    imgUrl: '/imgs/earphones3.webp',
  },
  {
    id: 4,
    name: 'Earphones 4',
    price: 79,
    imgUrl: '/imgs/earphones4.webp',
  },
  {
    id: 5,
    name: 'Earphones 5',
    price: 79,
    imgUrl: '/imgs/earphones5.webp',
  },
  {
    id: 6,
    name: 'Speaker',
    price: 89,
    imgUrl: '/imgs/speaker.webp',
  },
  {
    id: 7,
    name: 'Watch',
    price: 199,
    imgUrl: '/imgs/watch.webp',
  },
  {
    id: 8,
    name: 'Watch2',
    price: 299,
    imgUrl: '/imgs/watch2.webp',
  },
]

function Home() {
  return (
    <div
      key={'App-1'}
      style={{
        display: 'flex',
        flexWrap: 'wrap',
        justifyContent: 'center',
        gap: '20px',
      }}
    >
      {items.map((item, index) => (
        <Link
          key={`${index}-${item.id}`}
          style={{
            textDecoration: 'none',
            color: 'black',
          }}
          to={{
            pathname: `/product`,
            search:  JSON.stringify(item)
          }}
        >
         // our code ....
        </Link>
      ))}
    </div>
  )
}

export default App

And this is the modified Product.tsx page of yours.

import { useSearchParams } from "react-router-dom" import { Item } from "./App";

export function Product(){ 
    const [searchParam] = useSearchParams();
    let item = {} as Item;

    const data = Array.from(searchParam.keys());
    if(data.length > 0) {
        item= JSON.parse(data[0]);
    }
    return (<div>
        {
            item && item.id &&  <h1> {item.name}</h1>
            // Your code
        }
    </div>)
}
Faiz Ahmed
  • 396
  • 6
  • 13