[英]React Hooks setInterval memory leak
I have created a countdown timer component that passes the data to another component, and I use setTimeout
.我创建了一个倒数计时器组件,将数据传递给另一个组件,我使用
setTimeout
。 The component works as expected but an warning appears in my console:该组件按预期工作,但我的控制台中出现警告:
Warning: Can't perform a React state update on an unmounted component.
警告:无法对未安装的组件执行 React state 更新。 This is a no-op, but it indicates a memory leak in your application.
这是一个无操作,但它表明您的应用程序中存在 memory 泄漏。 To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
要修复此问题,请在 useEffect 清理 function 中取消所有订阅和异步任务。
As I use setTimeout
in useEffect
I tried to add clearInterval
in a return function, but this doesn't seem to help.当我在
useEffect
中使用setTimeout
时,我尝试在返回 function 中添加clearInterval
,但这似乎没有帮助。 Bellow you can find my component:您可以在下面找到我的组件:
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;
}
If I try to imitate clear from somewhere else place by adding another useEffect
right under the last one, like so:如果我尝试通过在最后一个下方添加另一个
useEffect
来从其他地方模仿 clear,如下所示:
useEffect(() => {
setTimeout(() => clearInterval(interval.current), 15000)
}, [])
Warning disappears but the countdown will not working any more.警告消失,但倒计时将不再起作用。 So how do I make this right, to not affect the countdown and clear the warning?
那么我该如何做到这一点,不影响倒计时并清除警告呢?
The clean up function for a useEffect
hook [1] needs to be returned from the function you give to useEffect
.需要从您提供给 useEffect 的 function 中返回用于
useEffect
挂钩 [1] 的清理useEffect
。 You are returning your clean up function in the function you give to setInterval
.您将在 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 [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;
};
}, []);
You could view the my full answer "Cleanup memory leaks on an Unmounted Component in React Hooks" right here: https://stackoverflow.com/a/59956926/4386148您可以在此处查看我的完整答案“Cleanup memory 在 React Hooks 中的未安装组件上泄漏” : https://stackoverflow.com/a/59956926/4386148
You don't need createRef
for effects
.您不需要
createRef
effects
。 and return should be after the interval
.并且返回应该
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);
};
}, []);
I use https://usehooks-ts.com/react-hook/use-interval我使用https://usehooks-ts.com/react-hook/use-interval
npm i usehooks-ts
Sample code in the url. url 中的示例代码。 Stable use of memory.
稳定使用memory。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.