Search code examples
javascriptreactjsrenderinge-commerce

How to Pass an index / value to different cards in react. Only last item appears


In Short, Let's assume that I have a list of items that I am displaying, and on each item there is a button, like a Quick View button to view extra information about the product in a modal pop-up. Now, everything is working perfectly, except when I click on the button, it brings the information related to the last item of my API/JSON file .. whatever the source of the file is. So, the last item in the Array. when I console.log(index) it brings the correct index for each card, but it doesn't show the information about each product separately.

import React, { Component } from "react";
import { productsInfo } from "./ProductsData";  //  the JS file containing the data
import Modal from "react-modal";
import "./Products.css";
import ProductDetailsPopUp from "./ProductDetailsPopUp";
import axios from "axios";

Modal.setAppElement("#root");
export default class Products extends Component {
  state = {
    productsData: [],
    modalIsOpen: false,
  };
  
  OpenModal = () => {
    this.setState({ modalIsOpen: true });
  };
  CloseModal = () => {
    this.setState({ modalIsOpen: false });
  };
  changeProduct = (item, index) => {
    this.setState({ showProduct: item });
  };
  render() {
    // const {id, img, title, price, isNew, country, currency} = productsInfo

    return (
      <div className="ProductsContainer">
        {productsInfo.map((item, index) => {
          return (
            <div className="cardHolder" key={item.id}>
              <img src={item.img} alt="Products" />
              <button
                onClick={() => {
                  this.OpenModal();
                  console.log(index);
                }}
                className="MainProductBtn"
              >
                QUICK VIEW
              </button>
              <Modal
                key={index}
                className="mainModal"
                style={{
                  overlay: {
                    backgroundColor: "#3333",
                    opacity: 0.4,
                    transition: "0.4s",
                  },
                }}
                isOpen={this.state.modalIsOpen}
                onRequestClose={this.CloseModal}
              >
                <div className="popupHeader" key={item.id}>
                  <h3>{item.title}</h3>
                  <button onClick={this.CloseModal}>×</button>
                </div>
                <ProductDetailsPopUp />
              </Modal>
              <p>{item.title}</p>
              <small>{`${item.price} USD`}</small>
            </div>
          );
        })}
      </div>
    );
  }
}



I tried including the index in onClick function and also passing it in the state, didn't work


Solution

  • You create Modal for every item inside your map method meaning that it will display productsInfo.length modals and the last one will be on top.

    Remote Modal tag from the map method and onClick set the current item at your state, change the display of the dialog to true and read the current item from the state inside your Modal.

    e.g.

      state = {
        productsData: [],
        modalIsOpen: false,
        currentItem: null
      };
    
      OpenModal = item => {
        this.setState({ modalIsOpen: true, currentItem: item });
      };
    
                onClick={() => {
                  this.OpenModal(item);
                  console.log(index);
                }}