我在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>
);
})}
但是结果是一样的…
替换了map函数外的模态和它的保存容器,并传递了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>
</>
);
您的onOpenModal
打开所有模态。最好的方法是将vid逻辑提取到它自己的组件中,并像这样调用它们:
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>
);
})}
);
}