React-player:无法播放映射数组中的选定项目

React-player: unable to play just selected item from mapped array

我在 nextjs-app 中使用 react-player 来显示通过 youtube-api 获取的视频。 一切正常,点击 playBtn 后模式打开,但播放器播放所有视频,而不仅仅是选定的视频。我真的不知道为什么,因为我将 videoId 设置为 url 的 RectPlayer 动态。有人能告诉我我做错了什么吗? 这是来源:

export default function Playlist({ videos }) {

  const [open, setOpen] = useState(false);

  const onOpenModal = () => setOpen(true);
  const onCloseModal = () => setOpen(false);

  const videoURL = "https://www.youtube.com/watch?v=";

  const sortedVids = videos
    .sort((a, b) =>
      Number(
        new Date(b.contentDetails.videoPublishedAt) -
          Number(new Date(a.contentDetails.videoPublishedAt))
      )
    )

return (
...

 {sortedVids.map((vid, id) => {
                return (
                    <div className={styles.item_container} key={id}>
                      <div className={styles.clip_container}>
                        <Image
                          className={styles.thumbnails}
                          src={vid.snippet.thumbnails.medium.url}
                          layout="fill"
                          objectFit="cover"
                          alt={vid.snippet.title}
                        />
                        <button
                          className={styles.playBtn}
                          onClick={onOpenModal}
                        >
                          <Image
                            src="/images/play.svg"
                            width="60"
                            height="60"
                          />
                        </button>
                        <div>
                          <Modal
                            open={open}
                            onClose={onCloseModal}
                            center
                            classNames={{
                              overlay: "customOverlay",
                              modal: "customModal",
                              overlayAnimationIn: "customEnterOverlayAnimation",
                              overlayAnimationOut:
                                "customLeaveOverlayAnimation",
                              modalAnimationIn: "customEnterModalAnimation",
                              modalAnimationOut: "customLeaveModalAnimation",
                            }}
                            animationDuration={800}
                          >
                            <ReactPlayer
                              playing={true}
                              url={
                                videoURL + `${vid.snippet.resourceId.videoId}`,
                              }
                              width="100%"
                              height="calc(100vh - 100px)"
                            />
                          </Modal>
                        </div>
                      </div>
                      <div className={styles.details_container}>
                        <h3>{vid.snippet.title}</h3>
                      </div>
                    </div>
                );
              })}
           );
          }

更新: 我尝试使用这样的第二个状态:

const [modalIsOpen, setModalIsOpen] = useState(false);
const [modalData, setModalData] = useState(null);

{sortedVids
            .filter((v) => v.snippet.title !== 'Private video')
            .map((vid, id) => {
              return (
                <div className={styles.item_container} key={id}>
                  <div className={styles.clip_container}>
                    <Image
                      className={styles.thumbnails}
                      src={vid.snippet.thumbnails.medium.url}
                      layout='fill'
                      objectFit='cover'
                      alt={vid.snippet.title}
                    />
                    <button
                      className={styles.playBtn}
                      onClick={() => {
                        setModalData(vid.snippet.resourceId.videoId);
                        console.log(modalData);
                        setModalIsOpen(true);
                      }}
                    >
                      <Image src='/images/play.svg' width='60' height='60' />
                    </button>
                    <div>
                      <Modal
                        key={modalData}
                        open={modalIsOpen}
                        onClose={() => setModalIsOpen(false)}
                        center
                        classNames={{
                          overlay: 'customOverlay',
                          modal: 'customModal',
                          overlayAnimationIn: 'customEnterOverlayAnimation',
                          overlayAnimationOut: 'customLeaveOverlayAnimation',
                          modalAnimationIn: 'customEnterModalAnimation',
                          modalAnimationOut: 'customLeaveModalAnimation',
                        }}
                        animationDuration={800}
                      >
                        <ReactPlayer
                          playing={true}
                          url={videoURL + `${modalData}`}
                          width='100%'
                          height='calc(100vh - 100px)'
                        />
                      </Modal>
                    </div>
                  </div>
                  <div className={styles.details_container}>
                    <h3>{vid.snippet.title}</h3>
                  </div>
                </div>
              );
            })}

但结果是一样的...

您的 onOpenModal 打开所有模型。最好的方法是将视频逻辑提取到它自己的组件中并像这样调用它们:

export default function Playlist({ videos }) {

  const videoURL = "https://www.youtube.com/watch?v=";

  const sortedVids = videos
    .sort((a, b) =>
      Number(
        new Date(b.contentDetails.videoPublishedAt) -
          Number(new Date(a.contentDetails.videoPublishedAt))
      )
    )

return (
...

 {sortedVids.map((vid, id) => {
                return (<MagicVidComponent vid={vid}/>)
   }
  })
}

const MagicVidComponent = (vid) => {
  const [open, setOpen] = useState(false);

  const onOpenModal = () => setOpen(true);
  const onCloseModal = () => setOpen(false);

return (
  <div className={styles.clip_container}>
                        <Image
                          className={styles.thumbnails}
                          src={vid.snippet.thumbnails.medium.url}
                          layout="fill"
                          objectFit="cover"
                          alt={vid.snippet.title}
                        />
                        <button
                          className={styles.playBtn}
                          onClick={setIdToOpen(id)}
                        >
                          <Image
                            src="/images/play.svg"
                            width="60"
                            height="60"
                          />
                        </button>
                        <div>
                          <Modal
                            open={idToOpen === id}
                            onClose={onCloseModal}
                            center
                            classNames={{
                              overlay: "customOverlay",
                              modal: "customModal",
                              overlayAnimationIn: "customEnterOverlayAnimation",
                              overlayAnimationOut:
                                "customLeaveOverlayAnimation",
                              modalAnimationIn: "customEnterModalAnimation",
                              modalAnimationOut: "customLeaveModalAnimation",
                            }}
                            animationDuration={800}
                          >
                            <ReactPlayer
                              playing={true}
                              url={
                                videoURL + `${vid.snippet.resourceId.videoId}`,
                              }
                              width="100%"
                              height="calc(100vh - 100px)"
                            />
                          </Modal>
                        </div>
                      </div>
                      <div className={styles.details_container}>
                        <h3>{vid.snippet.title}</h3>
                      </div>
)
}

但是你可以快速而肮脏地做类似的事情:

export default function Playlist({ videos }) {

  const [idToOpen, setIdToOpen] = useState();


  const onCloseModal = () => setIdToOpen(undefined);

  const videoURL = "https://www.youtube.com/watch?v=";

  const sortedVids = videos
    .sort((a, b) =>
      Number(
        new Date(b.contentDetails.videoPublishedAt) -
          Number(new Date(a.contentDetails.videoPublishedAt))
      )
    )

return (
...

 {sortedVids.map((vid, id) => {
                return (
                    <div className={styles.item_container} key={id}>
                      <div className={styles.clip_container}>
                        <Image
                          className={styles.thumbnails}
                          src={vid.snippet.thumbnails.medium.url}
                          layout="fill"
                          objectFit="cover"
                          alt={vid.snippet.title}
                        />
                        <button
                          className={styles.playBtn}
                          onClick={setIdToOpen(id)}
                        >
                          <Image
                            src="/images/play.svg"
                            width="60"
                            height="60"
                          />
                        </button>
                        <div>
                          <Modal
                            open={idToOpen === id}
                            onClose={onCloseModal}
                            center
                            classNames={{
                              overlay: "customOverlay",
                              modal: "customModal",
                              overlayAnimationIn: "customEnterOverlayAnimation",
                              overlayAnimationOut:
                                "customLeaveOverlayAnimation",
                              modalAnimationIn: "customEnterModalAnimation",
                              modalAnimationOut: "customLeaveModalAnimation",
                            }}
                            animationDuration={800}
                          >
                            <ReactPlayer
                              playing={true}
                              url={
                                videoURL + `${vid.snippet.resourceId.videoId}`,
                              }
                              width="100%"
                              height="calc(100vh - 100px)"
                            />
                          </Modal>
                        </div>
                      </div>
                      <div className={styles.details_container}>
                        <h3>{vid.snippet.title}</h3>
                      </div>
                    </div>
                );
              })}
           );
          }

替换了地图函数之外的模式,它包含容器并传递了 modalDate onClick。此代码对我有用:

const [modalIsOpen, setModalIsOpen] = useState(false);
  const [modalData, setModalData] = useState(null);

  const videoURL = "https://www.youtube.com/watch?v=" + modalData;

 return (
    <>
     ...
          {sortedVids
            .map((vid, id) => {
              return (
                <div className={styles.item_container} key={id}>
                  <div className={styles.clip_container}>
                    <button
                      className={styles.playBtn}
                      onClick={() => {
                        setModalData(vid.snippet.resourceId.videoId);
                        console.log(modalData);
                        setModalIsOpen(true);
                      }}
                    >
                      <Image src="/images/play.svg" width="60" height="60" />
                    </button>
                  </div>
                </div>
              );
            })}
        </div>
        <div>
          <Modal
            open={modalIsOpen}
            onClose={() => setModalIsOpen(false)}
            center > 
            <ReactPlayer
              playing={true}
              url={videoURL}
              config={{
                youtube: {
                  playerVars: {
                    autoplay: 1,
                    controls: 1,
                  },
                },
              }}
            />
          </Modal>
        </div>
      </div>
    </>
  );