首页 > 解决方案 > 如何使用 React 将数据从列表传递到另一个组件?

问题描述

我陷入了我的代码的一部分。基本上我有一个列表,我想在单击项目时显示更多信息,我有一个模态,我想在模态上显示这个细节。我设法传递了一些信息,但是,当我传递数组时,它只显示列表中的最后一项,我想准确显示我点击的那个。

**MODAL COMPONENT**

const Modal = ({ object, modal, setModal }) => {
  if (modal)
    return (
      <div className="modal">
        <div className="modal-body">
          <div className="modal-header">
            <span className="modal-title">{object.title}</span>
            <span className="modal-date">xxxxx</span>
          </div>
          <div className="modal-content">
            <div>
              <span className="sinopse-style">Overview</span>
              <hr></hr>
              <p className="modal-description">xxx</p>
            </div>
          </div>
          <div className="modal-footer">
            <div className="tags">
              <p className="tag-style">Ação</p>
              <p className="tag-style">Aventura</p>
              <p className="tag-style">Fantasia</p>
            </div>
            <div className="match-background">
              <span className="match-title">75%</span>
            </div>
          </div>

          <h1 onClick={() => setModal(false)}>Close Modal</h1>
        </div>
      </div>
    );
  return null;
};

export default Modal;

**RESULTS COMPONENT**

const Movies = (props) => {
  const [data, setData] = React.useState("");
  const [modal, setModal] = React.useState(false);
  const [currentPage, setCurrentPage] = React.useState(1);
  const [dataPerPage, setDataPerPage] = React.useState(5);

  React.useEffect(() => {
    const fetchData = async () => {
      await fetch(API).then((response) =>
        response
          .json()
          .then((json) => setData(json))
          .catch((error) => console.log(error))
      );
    };
    fetchData();
  }, []);

  function openModal() {
    !modal ? setModal(true) : setModal(false);
  }

  // Get data per page
  const indexLastData = currentPage * dataPerPage;
  const indexFirstData = indexLastData - dataPerPage;
  const currentData = data && data.results.slice(indexFirstData, indexLastData);

  // console.log("current: " + data && currentData);

  const paginate = (pageNumber) => setCurrentPage(pageNumber);

  return (
    <>
      {data &&
        currentData.map((object) => (
          <div className="movies-container" key={object.id} onClick={openModal}>
            <div>
              <img
                className="movie-billboard"
                src={`https://image.tmdb.org/t/p/w185${object.poster_path}`}
              />
            </div>
            <div className="rightSideMovie">
              <div className="header-movie-title">
                <span className="movie-title">{object.title}</span>
              </div>
              <div className="match">
                <span className="match-percentual">
                  {object.vote_average * 10}%
                </span>
              </div>
              <span className="release-date">{object.release_date}</span>
              <div className="movie-description">
                <span>{object.overview}</span>
              </div>
            </div>
            <Modal modal={modal} object={object} setModal={setModal} />
          </div>
        ))}
      <Pagination
        dataPerPage={dataPerPage}
        totalData={data && data.results.length}
        paginate={paginate}
      />
    </>
  );
};

标签: javascriptreactjsapi

解决方案


您可以稍微调整您的代码以从列表中选择电影并且只有 1 个模态。现在只有最后一个模式将在那里,因为您在地图外使用状态。

**MODAL COMPONENT**

// No need to pass in modal -- just pass in the selectedMovie here because that is what you care about
const Modal = ({ selectedMovie, hideModal }) => {
  if (selectedMovie)
    return (
      <div className="modal">
        <div className="modal-body">
          <div className="modal-header">
            <span className="modal-title">{selectedMovie.title}</span>
            <span className="modal-date">xxxxx</span>
          </div>
          <div className="modal-content">
            <div>
              <span className="sinopse-style">Overview</span>
              <hr></hr>
              <p className="modal-description">xxx</p>
            </div>
          </div>
          <div className="modal-footer">
            <div className="tags">
              <p className="tag-style">Ação</p>
              <p className="tag-style">Aventura</p>
              <p className="tag-style">Fantasia</p>
            </div>
            <div className="match-background">
              <span className="match-title">75%</span>
            </div>
          </div>

          <h1 onClick={hideModal}>Close Modal</h1>
        </div>
      </div>
    );
  return null;
};

export default Modal;

**RESULTS COMPONENT**

const Movies = (props) => {
  const [data, setData] = React.useState("");
  // Just store the selected movie here 
  const [selectedMovie, setSelectedMovie] = useState(null);
  const [currentPage, setCurrentPage] = React.useState(1);
  const [dataPerPage, setDataPerPage] = React.useState(5);

  React.useEffect(() => {
    const fetchData = async () => {
      await fetch(API).then((response) =>
        response
          .json()
          .then((json) => setData(json))
          .catch((error) => console.log(error))
      );
    };
    fetchData();
  }, []);

  // Get data per page
  const indexLastData = currentPage * dataPerPage;
  const indexFirstData = indexLastData - dataPerPage;
  const currentData = data && data.results.slice(indexFirstData, indexLastData);

  // console.log("current: " + data && currentData);

  const paginate = (pageNumber) => setCurrentPage(pageNumber);

  return (
    <>
      {data &&
        currentData.map((object) => (
          <div className="movies-container" key={object.id} onClick={() => setSelectedMovie(object)}>
            <div>
              <img
                className="movie-billboard"
                src={`https://image.tmdb.org/t/p/w185${object.poster_path}`}
              />
            </div>
            <div className="rightSideMovie">
              <div className="header-movie-title">
                <span className="movie-title">{object.title}</span>
              </div>
              <div className="match">
                <span className="match-percentual">
                  {object.vote_average * 10}%
                </span>
              </div>
              <span className="release-date">{object.release_date}</span>
              <div className="movie-description">
                <span>{object.overview}</span>
              </div>
            </div>
          </div>
        ))}
      // Hiding the modal is just simply setting the selectedMovie to null
      <Modal selectedMovie={selectedMovie} hideModal={() => setSelectedMovie(null)} />
      <Pagination
        dataPerPage={dataPerPage}
        totalData={data && data.results.length}
        paginate={paginate}
      />
    </>
  );
};

推荐阅读