javascript 如何在reactjs - nextjs中更改页面时清除setTimeout

dbf7pr2w  于 2023-02-21  发布在  Java
关注(0)|答案(2)|浏览(118)

我在Nextjs项目中创建了一个幻灯片,但是我有一个bug。当用户点击一个链接时,页面发生了变化,我得到了一个Unhandled Runtime Error,我知道它是因为setTimeout函数调用了一个函数,并试图对一个在新页面上不存在的元素进行样式化。我如何在用户点击链接后清除setTimeout函数?
错误截图:

我的组件代码:

import { useEffect, useState } from "react";
import SlideContent from "./slide-content";
import SlideDots from "./slide-dots";
import SlideItem from "./slide-item";

const Slide = (props) => {
  const { slides } = props;
  const [slideLength, setSlideLength] = useState(slides ? slides.length : 0);
  const [slideCounter, setSlideCounter] = useState(1);

  const handleSlideShow = () => {
    if (slideCounter < slideLength) {
      document.querySelector(
        `.slide-content:nth-of-type(${slideCounter})`
      ).style.left = "100%";
      const setSlide = slideCounter + 1;
      setSlideCounter(setSlide);

      setTimeout(() => {
        document.querySelector(
          `.slide-content:nth-of-type(${setSlide})`
        ).style.left = 0;
      }, 250);
    } else {
      document.querySelector(
        `.slide-content:nth-of-type(${slideCounter})`
      ).style.left = "100%";
      setSlideCounter(1);
      setTimeout(() => {
        document.querySelector(`.slide-content:nth-of-type(1)`).style.left = 0;
      }, 250);
    }
  };

  useEffect(() => {
    if (slideLength > 0) {
      setTimeout(() => {
        handleSlideShow();
      }, 5000);
    }
  }, [slideCounter, setSlideCounter]);

  return (
    <>
      <div className="slide-button-arrow slide-next">
        <span className="carousel-control-prev-icon"></span>
      </div>
      <div className="slide">
        {slides.map((slide) => (
          <SlideContent key={`slide-${slide.id}`}>
            <SlideItem img={slide.img} title={slide.title} />
          </SlideContent>
        ))}
        <SlideDots activeDot={slideCounter} totalDots={slides} />
      </div>
      <div className="slide-button-arrow slide-prev">
        <span className="carousel-control-next-icon"></span>
      </div>
    </>
  );
};

export default Slide;

我在主页文件中使用幻灯片组件。

wlzqhblo

wlzqhblo1#

useEffect(() => {

    let timer;
    if (slideLength > 0) {
      timer=setTimeout(() => {
        handleSlideShow();
      }, 5000);
    }

    return () => {
      clearTimeout(timer);
    };
  }, [slideCounter, setSlideCounter]);
flvtvl50

flvtvl502#

你应该删除你的超时函数当组件卸载.(如果你使用旧语法有componentWillUnmount()函数)当你使用钩子你可以返回你的useEffect所以它将引起卸载函数.在你的情况下它将是这样的东西:

useEffect(() => {
    //define a temp for your timeout to clear it later
    let myTimeout;
    if (slideLength > 0) {
      //assign timeout function to the variable
      myTimeout = setTimeout(() => {
        handleSlideShow();
      }, 5000);
    }
    // this triggers when the component unmounts or gets re-rendered.
    // you can clear the timeout here.
    return () => {
        clearTimeout(myTimeout);
    }
  }, [slideCounter, setSlideCounter]);

你应该总是删除你的超时,因为你不想内存泄漏和性能问题.它可能不会给予你错误,但清除他们所有.
有一个老帖子,我猜你可以读here

相关问题