Skip to content

Rule · Lint

requestAnimationFrame loop in an effect without cancelAnimationFrame

lint/raf-without-cancelwarnvoid lintupdated

Why it matters

The loop keeps running after unmount (and duplicates on remount in Strict Mode), burning CPU/battery and calling setState on unmounted components.

How to fix it

Store the frame id and cancel it in the effect cleanup. Also pause off-screen loops via IntersectionObserver / visibilitychange.

Example

tsx
useEffect(() => {
  let id = 0
  const loop = (t: number) => { draw(t); id = requestAnimationFrame(loop) }
  id = requestAnimationFrame(loop)
  return () => cancelAnimationFrame(id)
}, [])

void lint reports 67 rules in this category. Static source checks with no browser: Tailwind v4 silent failures, Next.js 16 API traps, React render-body bugs, accessibility markup, SEO files and motion hygiene.