簡體   English   中英

React Hooks setInterval memory 泄漏

[英]React Hooks setInterval memory leak

我創建了一個倒數計時器組件,將數據傳遞給另一個組件,我使用setTimeout 該組件按預期工作,但我的控制台中出現警告:

警告:無法對未安裝的組件執行 React state 更新。 這是一個無操作,但它表明您的應用程序中存在 memory 泄漏。 要修復此問題,請在 useEffect 清理 function 中取消所有訂閱和異步任務。

當我在useEffect中使用setTimeout時,我嘗試在返回 function 中添加clearInterval ,但這似乎沒有幫助。 您可以在下面找到我的組件:

export default function createEvent(WrappedComponent) {
  const Event = props => {
    const [{ endDate }] = useState(props);
    const [days, setDays] = useState('');
    const [hours, setHours] = useState('');
    const [minutes, setMinutes] = useState('');
    const [seconds, setSeconds] = useState('');

    const interval = useRef();

    useEffect(() => {
      interval.current = setInterval(() => {
        const date = moment.unix(endDate).format('MM DD YYYY, h:mm a');
        const then = moment(date, 'MM DD YYYY, h:mm a');
        const now = moment();
        const countdown = moment(then - now);
        const daysFormat = countdown.format('D');
        const hoursFormat = countdown.format('HH');
        const minutesFormat = countdown.format('mm');
        const secondsFormat = countdown.format('ss');

        setDays(`${daysFormat} days`);
        setHours(hoursFormat);
        setMinutes(minutesFormat);
        setSeconds(secondsFormat);

        return () => {
          clearInterval(interval.current);
          interval.current = null;
        };
      }, 1000);
    }, []);

    return (
      <WrappedComponent
        days={days}
        hours={hours}
        minutes={minutes}
        seconds={seconds}
        {...props}
      />
    );
  };

  return Event;
}

如果我嘗試通過在最后一個下方添加另一個useEffect來從其他地方模仿 clear,如下所示:

  useEffect(() => {
    setTimeout(() => clearInterval(interval.current), 15000)
  }, [])

警告消失,但倒計時將不再起作用。 那么我該如何做到這一點,不影響倒計時並清除警告呢?

需要從您提供給 useEffect 的 function 中返回用於useEffect掛鈎 [1] 的清理useEffect 您將在 function 中返回您的清理 function 給setInterval

useEffect(() => {
  interval.current = setInterval(() => {
    const date = moment.unix(endDate).format('MM DD YYYY, h:mm a');
    const then = moment(date, 'MM DD YYYY, h:mm a');
    const now = moment();
    const countdown = moment(then - now);
    const daysFormat = countdown.format('D');
    const hoursFormat = countdown.format('HH');
    const minutesFormat = countdown.format('mm');
    const secondsFormat = countdown.format('ss');

    setDays(`${daysFormat} days`);
    setHours(hoursFormat);
    setMinutes(minutesFormat);
    setSeconds(secondsFormat);
  }, 1000);

  // move clean up function to here:
  return () => {
    clearInterval(interval.current);
    interval.current = null;
  };
}, []);

[1] https://reactjs.org/docs/hooks-effect.html

useEffect(() => {
      interval.current = setInterval(() => {
        const date = moment.unix(endDate).format('MM DD YYYY, h:mm a');
        const then = moment(date, 'MM DD YYYY, h:mm a');
        const now = moment();
        const countdown = moment(then - now);
        const daysFormat = countdown.format('D');
        const hoursFormat = countdown.format('HH');
        const minutesFormat = countdown.format('mm');
        const secondsFormat = countdown.format('ss');

        setDays(`${daysFormat} days`);
        setHours(hoursFormat);
        setMinutes(minutesFormat);
        setSeconds(secondsFormat);
      }, 1000);

  // Attention : return function cleanup for the function used in useEffect()
  return () => {
      clearInterval(interval.current);
      interval.current = null;
    };
}, []);

您可以在此處查看我的完整答案“Cleanup memory 在 React Hooks 中的未安裝組件上泄漏”https://stackoverflow.com/a/59956926/4386148

您不需要createRef effects 並且返回應該after the interval

useEffect(() => {
      const timer = setInterval(() => {
        const date = moment.unix(endDate).format('MM DD YYYY, h:mm a');
        const then = moment(date, 'MM DD YYYY, h:mm a');
        const now = moment();
        const countdown = moment(then - now);
        const daysFormat = countdown.format('D');
        const hoursFormat = countdown.format('HH');
        const minutesFormat = countdown.format('mm');
        const secondsFormat = countdown.format('ss');

        setDays(`${daysFormat} days`);
        setHours(hoursFormat);
        setMinutes(minutesFormat);
        setSeconds(secondsFormat);

      }, 1000);

       return () => {
          clearInterval(timer);
        };
    }, []);

我使用https://usehooks-ts.com/react-hook/use-interval

npm i usehooks-ts

url 中的示例代碼。 穩定使用memory。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM