React modal on array list

Viewed 1947

need some help with this :D

I am trying to pull my array as list. On each list click (each list contains data from array) to open correct modal that will contain the rest of the info's from the array data file. Also I am not able to pull the array through my const Details so it can show me data I need, not sure how. I my other file i call out the component only.

Here is my code:

import React, { useState } from "react";

//ProductsData
import { ProductData } from "../products/data";

const Products = () => {
  const [showModal, setshowModal] = useState(false);
  const [hasClass, changeClass] = useState({
    activeObject: null,
    objects: ProductData.map((product) => {
      return product.id;
    }),
  });

  function toggleActive(index) {
    setshowModal(true);
    changeClass({ ...hasClass, activeObject: hasClass.objects[index] });
  }

  function toggleActiveClass(index) {
    if (hasClass.objects[index] === hasClass.activeObject) {
      return "active";
    } else {
      return "inactive";
    }
  }

  const Details = (ProductData) => (
    <div id="productModal" className={toggleActiveClass()}>
      <div className="product-img-holder">
        <img src={product.image} alt="img" />
      </div>
      <div className="product-details">
        <span className="list-title">
          {product.name}
          <br /> <span>{product.subtitle}</span>
        </span>
        <span className="list-grams">{product.grams}</span>
        <span className="list-price">{product.price}</span>
        <span className="list-desc">{product.desc}</span>
        <span className="list-cart">{product.cart}</span>
      </div>
    </div>
  );

  return (
    <>
      <ul className="list-menu">
        {ProductData.map((product, index) => (
          <li
            key={index}
            onClick={() => toggleActive(index)}
            className={toggleActiveClass(index)}
          >
            <span className="list-title">
              {product.name} <br /> <span>{product.subtitle}</span>
            </span>
            <span className="list-grams">{product.grams}</span>
            <span className="list-price">{product.price}</span>
          </li>
        ))}
      </ul>
      {showModal ? <Details /> : null}
    </>
  );
};

export default Products;

Thank you for you help.

1 Answers

Here is working example:

import React, { useState } from "react";

const productData = [
  { id: 1, label: "product1", description: "description1" },
  { id: 2, label: "product2", description: "description2" },
  { id: 3, label: "product3", description: "description3" },
  { id: 4, label: "product4", description: "description4" },
  { id: 5, label: "product5", description: "description5" },
  { id: 6, label: "product6", description: "description6" },
  { id: 7, label: "product7", description: "description7" },
];

const Products = () => {
  const [showModal, setShowModal] = useState(false);
  const [activeObject, setActiveObject] = useState(null);

  function getClass(index) {
    return index === activeObject?.id ? "active" : "inactive";
  }

  // here className can not be "inactive" since Modal always shows activeObject
  const Modal = ({ object: { label, description } }) => (
    <div id="productModal" className="active">
      This is modal
      <h2>{label}</h2>
      <span className="description">{description}</span>
      <button onClick={() => setShowModal(false)}>Close me</button>
    </div>
  );

  return (
    <>
      <ul className="list-menu">
        {productData.map(({ id, label, description }) => (
          <li
            key={id}
            onClick={() => {
              setActiveObject({ id, label, description });
              setShowModal(true);
            }}
            className={getClass(id)}
          >
            <h2>{label}</h2>
          </li>
        ))}
      </ul>
      {showModal ? <Modal object={activeObject} /> : null}
    </>
  );
};

export default Products;
Related