将 setTimeout 函数与设置特定状态的箭头函数一起使用时出现问题

Problem with using setTimeout function together with an arrow function that sets a particular state

我正在尝试复制当您将鼠标悬停在 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}
    >
...