question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Blazor component removed from DOM before disposal causes js interop to fail

See original GitHub issue

I’ve already posted this on SO without success.

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

My Blazor component has some associated JavaScript, which performs (async) animations.

MyComponent.razor

protected override async Task OnAfterRenderAsync(bool firstRender)
{
  if (someCondition & jsModule != null)
    await jsModule.InvokeVoidAsync("startAnimation", "#my-component");
}


public async ValueTask DisposeAsync()
{
  if (jsModule != null)
    await jsModule.InvokeVoidAsync("stopAnimationPrematurely", "#my-component");
}

MyComponent.razor.js

export function startAnimation(id) {
  let element = document.getElementById(id);
  element.addEventListener(
    'animationend',
    function() { element.classList.remove("cool-animation") },
    { once: true }
  );
  element.classList.add("cool-animation");
}


export function stopAnimationPrematurely(id) {
  let element = document.getElementById(id);      // fails here
  element.removeEventListener(
    'animationend',
    function() { element.classList.remove("cool-animation") },
    { once: true }
  );
  element.classList.remove("cool-animation");
}

As you can see, the animation cleans up after itself (via { once: true }).

However when the user clicks to a different page or component - and thus the blazor component is destroyed - there could be an animation in progress. If I don’t remove the js event listener then I’ll get a memory leak. So in DisposeAsync() I invoke js cleanup code which explicitly calls removeEventListener().

The problem is that by the time the js code runs, the component is already destroyed - so the DOM element is missing, the id is invalid, and thus the js cleanup fails (and throws).

Expected Behavior

This is very surprising. There is a race condition between the various lifecycle methods and disposal.

In MudBlazor they also encountered this and introduced all sorts of locking workarounds.

Steps To Reproduce

See code above.

Exceptions (if any)

JS errors: document.getElementById(id) fails because id refers to an element no longer part of the DOM.

.NET Version

6.0.404

Anything else?

Thanks.

Issue Analytics

  • State:closed
  • Created 9 months ago
  • Comments:6 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
guardrexcommented, Dec 27, 2022

@lonix1 … It’s already covered in both docs at …

However … @javiercn

I have it down for Blazor Server only scenarios. Currently, the coverage focuses on cleanup after the SignalR circuit is destroyed. Seems like I should broaden it out to cover Blazor WASM (and Server, really) for the element is MIA from the DOM 💥 case (… and perhaps mention the renderer is gone for Server, too). Is that correct?

0reactions
lonix1commented, Dec 27, 2022

@guardrex Yes I should have mentioned this was for blazor wasm.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Blazor component removed from DOM before disposal ...
The problem is that by the time the js code runs, the component is already destroyed - so the DOM element is missing,...
Read more >
ASP.NET Core Blazor JavaScript interoperability (JS interop)
The component may have been removed from the DOM by the time your cleanup code executes in Dispose{Async} . In a Blazor Server...
Read more >
Guide to Blazor JavaScript Interop - Imaginet Blog
Learn how to use Blazor JavaScript Interop to make JavaScript and .NET code interact seamlessly. Get up and running quickly with step-by-step..
Read more >
Identifying what is causing interop errors : r/Blazor
In my (albeit limited) experience I've found this error occurs after another error has killed your connection. Probably your library (mudblazor ...
Read more >
JavaScript Errors - Telerik UI for Blazor
The telerik-blazor.js JS Interop file is missing or the URL is wrong; The defer attribute causes the script to load and execute too...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found