reactjs - 将 setTimeout 函数与设置特定状态的箭头函数一起使用时出现问题
问题描述
我试图复制当您将鼠标悬停在 Netflix 上的特定电影磁贴上时,电影磁贴有时会展开以显示更多信息时的方式。
目前,我已成功扩展磁贴以在悬停时显示更多信息,但设置超时以使信息仅在鼠标悬停超过 1000 毫秒后才显示,这证明会产生不需要的结果。
到目前为止,我已经尝试过了,但问题是当我悬停时,所有其他电影图块的状态都会改变,而不仅仅是悬停的那个
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;
解决方案
在您提供的代码中,渲染时会调用超时。因此,每个渲染的电影图块的状态都会发生变化。要在触发事件时调用 setTimeout,您需要将其包装在一个函数中:
...
onMouseEnter={() => setTimeout(() => setisHovered(true), 1000)}
...
对于行为“鼠标悬停超过 1000 毫秒后显示信息”,您将需要更多代码:
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}
>
...
推荐阅读
- ms-word - 如何保留从 Docx 到 Google doc 的内容控制和自定义 XML 架构?
- oauth-2.0 - OpenID Connect/OAuth2 用户同步协议扩展
- android - Android中的线程没有停止问题
- bash - 使用 Git Bash 运行 npm install global 时出现 EPERM 错误?
- javascript - 实时 Javascript 过滤不起作用引发未定义
- php - PHP中的ldap认证品种
- javascript - 如何在不使用 javascript 中的画布的情况下创建一个在击中边界时弹跳的球?
- algorithm - 如何从非常大的集合中找到最佳的参数组合?
- android - java.lang.IllegalArgumentException:无效的主题名称:الصحة_التغذية 与允许的格式不匹配 [a-zA-Z0-9-_.~%]{1,900}
- java - 带有混合 Kotlin/Java 项目的 Sonarqube 报告 Kotlin 文件上的 Java 问题