Reputation: 130
I am trying to replicate how when you hover over a particular movie tile on Netflix, after sometime the movie tile expands to display more information.
Currently I have succeeded on expanding the tile to display more information on hover but setting a timeout such that the information is only displayed after the mouse has hovered for over 1000ms is proving to produce unwanted results.
So far i have tried this but the problem is that when i hover the state is changed for all other movie tiles instead of only the one that was hovered
function RowPoster({ movie, isTrending }) {
const [isHovered, setisHovered] = useState(false);
const trailerUrl = movie.trailer_url;
return (
<div
className={`RowPoster ${isTrending && "isTrending"}`}
onMouseEnter={setTimeout(() => setisHovered(true), 1000)}
onMouseLeave={() => setisHovered(false)}
>
<img src={movie.cover_image} alt={movie.titles.en} />
{isHovered && (
<>
{
<ReactPlayer
className="video"
width="100%"
height="160px"
loop={true}
playing={false}
url={trailerUrl}
/>
}
<div className="item__info">
<h4>{movie.titles.en}</h4>
<div className="icons">
<PlayArrow className="icon" />
<Add />
<ThumbUpAltOutlined className="icon" />
<ThumbDownOutlined className="icon" />
<KeyboardArrowDown className="icon" />
</div>
<div className="stats">
<span className="stats_score">{`Score ${movie.score}%`}</span>
</div>
<div className="genre">
<ul className="genre_items">
<li>{movie.genres[0]}</li>
<li>{movie.genres[1]}</li>
<li>{movie.genres[2]}</li>
<li>{movie.genres[3]}</li>
</ul>
</div>
</div>
</>
)}
</div>
);
}
export default RowPoster;
Upvotes: 0
Views: 341
Reputation: 266
In the code you provided, a timeout is called when rendering. For this reason, the state changes for each movie tiles that is rendered. To call setTimeout when an event is fired, you need to wrap it in a function:
...
onMouseEnter={() => setTimeout(() => setisHovered(true), 1000)}
...
For behavior "display information after the mouse has hovered for more than 1000 ms", you will need a little more code:
function RowPoster({ movie, isTrending }) {
const [isHovered, setisHovered] = useState(false);
const trailerUrl = movie.trailer_url;
const hoverTimerRef = useRef();
const handleCancelHover = useCallback(() => {
if (hoverTimerRef.current) {
clearTimeout(hoverTimerRef.current);
}
}, []);
const handleMouseEnter = useCallback(() => {
// save the timer id in the hoverTimerRef
hoverTimerRef.current = setTimeout(() => setisHovered(true), 1000);
}, []);
const handleMouseLeave = useCallback(() => {
// cancel the scheduled hover if the mouseLeave event is fired before the timer is triggered
handleCancelHover();
setisHovered(false);
}, [handleCancelHover]);
useEffect(() => {
return () => {
// cancel the scheduled hover when unmounting the component
handleCancelHover();
};
}, [handleCancelHover]);
return (
<div
className={`RowPoster ${isTrending && "isTrending"}`}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
...
Upvotes: 1