[英]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;
};
}, []);
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);
};
}, []);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.