Skip to content

fix memory leak issue using unmounted #220

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jonesie100
Copy link

I'm having a memory leak issue just like shown in PR#196,

Decided to give it a try with something similar to what he had done.

Copy link

vercel bot commented Jan 20, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
auto-animate ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jan 20, 2025 9:23pm

@apappas1129
Copy link

apappas1129 commented Aug 7, 2025

Don't you need to do the following as well?:

parents.delete(el);
enabled.delete(el);
options.delete(el);
coords.delete(el);
siblings.delete(el);

const parentAnimation = animations.get(el);
if (parentAnimation) {
  parentAnimation.cancel();
  animations.delete(el);
}

const parentObserver = intersections.get(el);
if (parentObserver) {
  parentObserver.disconnect();
  intersections.delete(el);
}

const parentInterval = intervals.get(el);
if (parentInterval) {
  clearInterval(parentInterval);
  intervals.delete(el);
}

const parentDebounce = debounces.get(el);
if (parentDebounce) {
  clearTimeout(parentDebounce);
  debounces.delete(el);
}

There are a bunch of collections that might need the clean up too. For the associated child elements:

forEach(el, (child) => {
  // Cancel any running animations
  const animation = animations.get(child);
  if (animation) {
    animation.cancel();
    animations.delete(child);
  }

  // Disconnect intersection observer
  const observer = intersections.get(child);
  if (observer) {
    observer.disconnect();
    intersections.delete(child);
  }

  // Clear polling interval
  const interval = intervals.get(child);
  if (interval) {
    clearInterval(interval);
    intervals.delete(child);
  }

  // Clear debounce timeout
  const debounce = debounces.get(child);
  if (debounce) {
    clearTimeout(debounce);
    debounces.delete(child);
  }

  // Clean up coordinates and siblings
  coords.delete(child);
  siblings.delete(child);
});

Lastly, we have to somehow trigger the mutations?.disconnect(). However, if autoAnimate is being used multiple times for different elements, in the current implementation, the the same MutationObserver instance is shared for all. So mutations?.disconnect() will disconnect the observer for all elements, not just that one instance of el. To fix this, we need a separate MutationObserver per element or some other way to track and disconnect only the observer for that specific el instance.

@apappas1129
Copy link

There are also a few more potential memory leaks from the following:

animation.addEventListener("finish", updatePos.bind(null, el))

animation.addEventListener("finish", updatePos.bind(null, el))

animation.addEventListener("finish", cleanUp.bind(null, el, styleReset))

These event listeners are never removed, and .bind() creates new function references that can't be removed later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants