Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
360 views
in Technique[技术] by (71.8m points)

reactjs - How do i want only the clicked items to appear on the modal?

I'm a beginner. Thank you in advance for sharing your knowledge.

I'm making a great search app by receiving Api data.

But I have a problem. The modal screen of the clicked item does not appear.

To be exact, the modal screen appears. But something else appears that I didn't click on.

The method in which the modal works is shown on the screen by finding the path to the id of the data in the Api.

This is the file of the problem. Seach.jsx

import styled from "styled-components";
import SearchForm from "../Components/SearchForm";
import Portal from "../Components/Portal";
import Modal from "../Components/Modal";

const Search = () => {
  const [searchTerm, setSearchTerm] = useState("");
  const [cocktails, setCocktails] = useState([]);
  const [open, setOpen] = useState(false);

  const handleOpen = (e) => {
    setOpen(true);
  };
  const handleClose = () => {
    setOpen(false);
  };
  useEffect(() => {
    const getDrinks = async () => {
      try {
        const response = await fetch(
          `https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${searchTerm}`
        );
        const data = await response.json();
        setCocktails(data);
      } catch (error) {
        console.log(error);
      }
    };
    getDrinks();
  }, [searchTerm]);

  return (
    <main style={{ width: "100%" }}>
      <SearchForm setSearchTerm={setSearchTerm} />
      <Wrapper className="cocktail-list">
        {cocktails.drinks.map(({ idDrink, strDrink, strDrinkThumb }) => (
          <>
            <Container
              className="cocktail"
              onClose={handleClose}
              onClick={handleOpen}
            >
              <Img>
                <img src={strDrinkThumb} alt={strDrink} />
              </Img>
              <Name key={idDrink}>{strDrink}</Name>
            </Container>
            {open && (
              <Portal>
                <Modal idDrink={`${idDrink}`} onClose={handleClose} />?
              </Portal>
            )}
          </>
        ))}
      </Wrapper>
    </main>
  );
};

export default Search;

? This is the modal part. I want to show modal only the clicked item.

However, the props that deliver to Modal send out all id of cocktails.drinks.

This file is Modal.jsx

import React, { useState, useEffect } from "react";
import axios from "axios";
import styled from "styled-components";
import Detail from "../Screens/Detail";

const MyModal = ({ onClose, idDrink }) => {
  const [data, setData] = useState([]);
  let id = idDrink;
  let url = `https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=${id}`;
  useEffect(() => {
    axios
      .get(url)
      .then((res) => {
        setData(res.data.drinks);
      })
      .catch((error) => {
        console.log(error);
      });
  }, [url]);
  return (
    <MyModals onClick={onClose}>
      <Detail idDrink={idDrink} />
    </MyModals>
  );
};

export default MyModal;

Search.jsx(the problem file) handed over Id to spreads the information on modals.

How can I get the id of the clicked item and hand it over to Modal.jsx?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You need to store an id of the selected item in the state of the Search component and then pass that id to the Modal component.

import styled from "styled-components";
import SearchForm from "../Components/SearchForm";
import Portal from "../Components/Portal";
import Modal from "../Components/Modal";

const Search = () => {
  const [searchTerm, setSearchTerm] = useState("");
  const [cocktails, setCocktails] = useState([]);
  const [open, setOpen] = useState(false);


  const [selectedItem, setSelectedItem] = useState("");


  const handleOpen = (idDrink) => {
    setSelectedItem(idDrink)
    setOpen(true);
  };
  const handleClose = () => {
    setOpen(false);
  };
  useEffect(() => {
    const getDrinks = async () => {
      try {
        const response = await fetch(
          `https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${searchTerm}`
        );
        const data = await response.json();
        setCocktails(data);
      } catch (error) {
        console.log(error);
      }
    };
    getDrinks();
  }, [searchTerm]);

  return (
    <main style={{ width: "100%" }}>
      <SearchForm setSearchTerm={setSearchTerm} />
      <Wrapper className="cocktail-list">
        {cocktails.drinks.map(({ idDrink, strDrink, strDrinkThumb }) => (
          <>
            <Container
              className="cocktail"
              onClose={handleClose}
              onClick={() => handleOpen(idDrink)}
            >
              <Img>
                <img src={strDrinkThumb} alt={strDrink} />
              </Img>
              <Name key={idDrink}>{strDrink}</Name>
            </Container>
          </>
        ))}

// You should keep modal outside the loop. Because it's rendering multiple Modals inside the loop and show all of them at once. When you trigger the hanldeOpen function.
 
      {open && (
              <Portal>
                <Modal idDrink={`${selectedItem}`} onClose={handleClose} />?
              </Portal>
            )}
      </Wrapper>
    </main>
  );
};

export default Search;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...