Reputation: 10915
I have created a Blazor Webassembly Project and added a key listener in JavaScript, which is listening to every key stroke on the DOM document. Everything works as expected, however when I open the Blazor page where the key listener is registered and later open it again, the following error occurs in the Web Browser:
There is no tracked object with id '2'. Perhaps the DotNetObjectReference instance was already disposed. (Parameter 'dotNetObjectId')
Obviously the object "dotnethelper" is disposed but the Javascript is still listening / getting called.
Basically I implemented the "Component instance .NET method helper class" from the Microsoft Documentation.
Note: The IDisposable is injected on the top and the Dispose function is getting called.
@code {
private KeyListenerInvokeHelper _keyListenerInvokeHelper;
private DotNetObjectReference<KeyListenerInvokeHelper>? objRef;
protected override async Task OnInitializedAsync()
{
objRef = DotNetObjectReference.Create(_keyListenerInvokeHelper);
await JS.InvokeVoidAsync("initializeKeyListener", objRef);
}
public void Dispose()
{
objRef?.Dispose();
}
}
window.initializeKeyListener = (dotnetHelper) => {
document.addEventListener('keydown', logKey);
function logKey(e) {
dotnetHelper.invokeMethod('OnKeyDown', e.key);
console.log('key down ' + e.key);
}
}
public class KeyListenerInvokeHelper
{
private readonly Action<string> action;
public KeyListenerInvokeHelper(Action<string> action)
{
this.action = action;
}
[JSInvokable("OnKeyDown")]
public void OnKeyDown(string key)
{
action.Invoke(key);
}
}
Upvotes: 6
Views: 7613
Reputation: 52365
When you dispose of your object, you need to remove the event listener as well. You mentioned I tried removing the eventlistener on the 'keydown' event.
, but perhaps the way you did it was not correct?
My javascript is a little rusty, but I think you could do something like the following:
var logkey;
window.initializeKeyListener = (dotnetHelper) => {
logkey = (e) => {
dotnetHelper.invokeMethod('OnKeyDown', e.key);
console.log('key down ' + e.key);
};
document.addEventListener('keydown', logkey);
}
window.removeKeyListener = () => {
document.removeEventListener('keydown', logkey);
}
and then in your component:
@implements IAsyncDisposable
public async ValueTask DisposeAsync()
{
await JSRuntime.InvokeVoidAsync("removeKeyListener");
objRef?.Dispose();
}
Having said that, perhaps calling a static method in C# using [JSInvokable]
would be better suited for your use case?
Upvotes: 6