You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用setTimeout设置hover状态时所有React电影卡片状态异常问题

问题核心原因

  1. 事件绑定写法错误:onMouseEnter需要接收函数作为回调,你直接传入setTimeout(...)会在组件渲染阶段就立即执行定时逻辑,返回的定时器ID被当成事件回调,所有卡片初始化时就会排队触发展开,才会出现所有卡片状态同时修改的问题。
  2. 缺少定时器清理机制:如果用户悬停不满1秒就移走鼠标,定时器不会被中断,仍然会在1秒后触发对应卡片展开,不符合交互需求。

修正后代码

import { useState, useRef, useEffect } from 'react';
import ReactPlayer from 'react-player';
// 图标组件导入按你原有逻辑保留即可

function RowPoster({ movie, isTrending }) {
  const [isHovered, setIsHovered] = useState(false);
  // 用ref存储定时器ID,避免组件重渲染导致引用丢失
  const hoverTimerRef = useRef(null);
  const trailerUrl = movie.trailer_url;

  // 组件卸载时清除残留定时器,避免内存泄漏
  useEffect(() => {
    return () => {
      if (hoverTimerRef.current) clearTimeout(hoverTimerRef.current);
    };
  }, []);

  return (
    <div
      className={`RowPoster ${isTrending && "isTrending"}`}
      onMouseEnter={() => {
        // 先清理残留定时器,避免重复触发
        if (hoverTimerRef.current) clearTimeout(hoverTimerRef.current);
        hoverTimerRef.current = setTimeout(() => setIsHovered(true), 1000);
      }}
      onMouseLeave={() => {
        // 鼠标移走先清定时器,悬停不满1秒不会触发展开
        if (hoverTimerRef.current) clearTimeout(hoverTimerRef.current);
        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">
                {movie.genres.map((genre, idx) => (
                  <li key={idx}>{genre}</li>
                ))}
              </ul>
            </div>
          </div>
        </>
      )}
    </div>
  );
}

export default RowPoster;

修改说明

  • 给onMouseEnter的定时逻辑套了一层回调函数,只有鼠标真正进入卡片时才会启动定时器,不会在组件渲染阶段就自动执行
  • 新增多处定时器清理逻辑,彻底避免误触发和内存泄漏问题
  • 优化了分类项渲染逻辑,改用map遍历避免硬编码索引可能出现的报错

内容的提问来源于stack exchange,提问作者Bradley Juma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 20:45:02