Reputation: 124
I'm trying to create a component that allows a video to autoplay on mouseenter and pauses on mouseleave. However, the current code causes all videos to autoplay when you put the mouseover any single one of the videos. How can I only make the video that you're interacting with update its state in a more isolated way?
I can't seem to find a solution using React hooks anywhere, that I can understand and implement into my own code.
export default function VideoGrid(props) {
const [playing, setPlaying] = useState(false);
return (
<div>
<div className={styles.VideoGrid}>
<div className="container">
<h2 className={styles.title + " text-lg uppercase title"}>{props.title}</h2>
<div className={styles.videos}>
{props.videos ? videos.output.map((video, index) => {
return (
<div className={styles.video} key={index}>
{ video.acf.video_url ? (
<ReactPlayer
controls={false}
playing={playing}
onMouseEnter={() => setPlaying(true)}
onMouseLeave={() => setPlaying(false)}
height={205}
url={video.acf.video_url + '&showinfo=0&controls=0&autohide=1'}
width='100%'
config= {{
youtube: {
playerVars: {showinfo: 0, controls: 0}
}
}}
/>
) : (
<img src={video._embedded ? video._embedded['wp:featuredmedia'][0].media_details.sizes.full.source_url : '/logo.svg'} height={205} />
)}
<p className="mt-2">{video.title.rendered}</p>
{video.acf.description && router.pathname != '/' ? <p className={styles.description + " text-xs"}>{video.acf.description}</p> : ''}
</div>
)
}) : ''}
</div>
</div>
</div>
</div>
)
}
Upvotes: 0
Views: 28
Reputation: 592
You can create a separate component and deal with the state individually.
const Video = (props) => {
const [playing, setPlaying] = useState(false);
return (
<div className={styles.video} key={index}>
{video.acf.video_url ? (
<ReactPlayer
controls={false}
playing={playing}
onMouseEnter={() => setPlaying(true)}
onMouseLeave={() => setPlaying(false)}
height={205}
url={video.acf.video_url + "&showinfo=0&controls=0&autohide=1"}
width="100%"
config={{
youtube: {
playerVars: { showinfo: 0, controls: 0 },
},
}}
/>
) : (
<img
src={
video._embedded
? video._embedded["wp:featuredmedia"][0].media_details.sizes.full
.source_url
: "/logo.svg"
}
height={205}
/>
)}
<p className="mt-2">{video.title.rendered}</p>
{video.acf.description && router.pathname != "/" ? (
<p className={styles.description + " text-xs"}>
{video.acf.description}
</p>
) : (
""
)}
</div>
);
};
export default Video;
Then render it in your map. You need to do the proper changes to pass your data into the video component.
export default function VideoGrid(props) {
return (
<div>
<div className={styles.VideoGrid}>
<div className="container">
<h2 className={styles.title + " text-lg uppercase title"}>
{props.title}
</h2>
<div className={styles.videos}>
{props.videos
? videos.output.map((video, index) => {
return <Video />;
})
: ""}
</div>
</div>
</div>
</div>
);
}
Upvotes: 1