Describe the external system
An effect is useful when a component must synchronize with something outside React rendering, such as a browser event subscription or a third-party widget. Start by naming that system and the values that configure it. If the code only transforms props into display data, an effect may add an unnecessary second update instead of solving an external synchronization problem.
Pair setup with its inverse
A resize listener should be removed, an interval cleared and an observer disconnected when the owning synchronization ends. Return a cleanup function that can refer to the exact resource created by that effect invocation. Keeping setup and cleanup adjacent makes ownership easier to review than storing unrelated global handles that several components can overwrite.
Use a concrete subscription example
Suppose a component listens for document visibility changes to pause a preview. Define the handler within the effect, attach it to the relevant event and remove that same handler in cleanup. If a new configuration requires a new handler, React can clean up the previous subscription before establishing the next one. The source should explain this relationship without relying on a mount-only mental model.
Treat development repetition as a useful check
React development checks can exercise a setup, cleanup and setup sequence to reveal lifecycle mistakes. A correct subscription should tolerate that sequence without leaving duplicate listeners or broken state. Avoid suppressing the behavior with a ref that merely prevents the second setup. That workaround can hide the missing inverse operation and leave real navigation or configuration changes unreliable.
Handle asynchronous completion ownership
When an effect starts a request, cleanup should cancel it where supported or mark its result irrelevant. Otherwise a response associated with an old query can update the current screen. Dependencies describe which values configure synchronization; omitting them to reduce reruns can preserve stale closures. Restructure the effect around the true external relationship instead of fighting the dependency list.
Verify repeated lifecycle transitions
Open and close the feature repeatedly, change its configuration and navigate away while work is pending. Confirm that only one active subscription remains and that outdated results are ignored. Check cleanup after an error as well as normal completion. A resource can appear harmless during one render yet accumulate during ordinary navigation, so repeated use is the meaningful test.
Further reading
Put the idea to work.
Explore free browser tools for images, text and developer workflows.