---
title: "Effect subscribes without cleanup (next/effect-cleanup)"
description: "Listeners, timers and observers created in an effect outlive the component and pile up each time the effect re-runs."
url: http://localhost:4173/rules/next/effect-cleanup
updated: 2026-11-11
---

# Effect subscribes without cleanup

> `next/effect-cleanup` is a vetd rule. It flags: Effect subscribes without cleanup. It runs on every `check`, together with the TypeScript check.

| Fact | Value |
| --- | --- |
| Rule id | `next/effect-cleanup` |
| Severity | warning |
| Group | React client code |
| Tags | react, correctness |

## Why it matters

Listeners, timers and observers created in an effect outlive the component and pile up each time the effect re-runs.

## How to fix it

Return a function that removes the listener / clears the timer / disconnects the observer.

## Credit

Based on work by:

- [React team](https://react.dev): Effects that subscribe to external systems must return a cleanup function that undoes the setup.

## References

- [Synchronizing with Effects (add cleanup if needed)](https://react.dev/learn/synchronizing-with-effects), React
- [useEffect – React](https://react.dev/reference/react/useEffect), React

## See it

Demos in the vetd Lab:

- [Stable effect dependencies](http://localhost:4173/lab/react-perf/stabilize-effect-subscriptions)
- [Share requests and listeners](http://localhost:4173/lab/react-perf/share-client-requests-and-listeners)

## Related rules

- [`next/async-effect`](http://localhost:4173/rules/next/async-effect.md)

## Get this text from vetd

MCP: call `explain` with `{ "diagnosticId": "next/effect-cleanup" }`. CLI: `npx vetd explain next/effect-cleanup`.

---

[All 92 rules](http://localhost:4173/rules.md) · Previous: [`next/fetch-in-effect`](http://localhost:4173/rules/next/fetch-in-effect.md) · Next: [`next/missing-metadata`](http://localhost:4173/rules/next/missing-metadata.md)
