Rules
no-leaked-timeout
Enforces that every 'setTimeout' in a component or custom hook has a corresponding 'clearTimeout'.
Full Name in eslint-plugin-react-web-api
react-web-api/no-leaked-timeoutFull Name in @eslint-react/eslint-plugin
@eslint-react/web-api-no-leaked-timeoutPresets
web-api
recommended
recommended-typescript
recommended-type-checked
strict
strict-typescript
strict-type-checked
Rule Details
Scheduling a timeout within the setup function of useEffect without canceling it in the cleanup function can lead to unwanted setTimeout callback executions and may also result in stale values captured by previous renders' effects after each subsequent re-render.
Common Violations
Invalid
import React, { useEffect, useState } from "react";
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
const timeoutId = setTimeout(() => console.log(count), 1000);
// ^^^ A 'setTimeout' created in 'useEffect' must be cleared in the cleanup function.
}, []);
return null;
}Valid
import React, { useEffect, useState } from "react";
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
const timeoutId = setTimeout(() => console.log(count), 1000);
return () => clearTimeout(timeoutId);
}, []);
return null;
}Resources
Further Reading
See Also
react-web-api/no-leaked-event-listener
Enforces that everyaddEventListenerin a component or custom hook has a correspondingremoveEventListener.react-web-api/no-leaked-interval
Enforces that everysetIntervalin a component or custom hook has a correspondingclearInterval.react-web-api/no-leaked-resize-observer
Enforces that everyResizeObservercreated in a component or custom hook has a correspondingResizeObserver.disconnect().