0

When ever refresh or manually navigate to a Blazor page that is using javascript interop, it errors out because the dispose function no longer exists in javascript.

Is there a way to not run "dispose" on a component that implements IDisposable when its a refresh or a navigation? Is there where the "ElementReference" type would help?

Here's some code for context:

My blazor component implements IDisposable:

@implements IDisposable

this runs my Dispose function, which calls on my interop file:

public void Dispose()
{
    JqxWindowJsInterop.Dispose();
}

my JsInterop runs this call to javascript:

public void Dispose()
    {
        jsRuntime.InvokeAsync<string>(
            "jqxWindowComponent.dispose",
            InstanceId);
        _JqxWindowJsInteropReference?.Dispose();
    }

which finally runs this in javascript:

window.jqxWindowComponent = {
dispose: function (instanceId) {
    console.log('jqxWindowComponent.dispose : ' + instanceId);
    if ($('#' + instanceId).length) {
        $('#' + instanceId).jqxWindow('destroy');
    }
    delete jqxWindowList[instanceId];       
}};

when I refresh or navigate to/from to this page through the browser I get this error

System.NullReferenceException: 'Object reference not set to an instance of an object.'MyNameSpace.Components.JqxWindowComponent.JqxWindowJsInterop.get returned null.

Any help appreciated.

Tom Crosman
  • 1,137
  • 1
  • 12
  • 37
  • What is the instanceId? Do you see if in the log files? Did you check log file? – jdweng Oct 29 '20 at 17:53
  • I assign my JavaScript components a generated guid, passed as InstanceId – Tom Crosman Oct 29 '20 at 17:54
  • Did you remove the instanceId? Exception could be caused by the instance being deleted before the JaveScript is run. – jdweng Oct 29 '20 at 17:58
  • The dispose removes the instance. It runs correctly when navigating using the Blazor site, just crashes when navigating manually with the browser URL – Tom Crosman Oct 29 '20 at 18:01
  • You may have a timing issue and just lucky it doesn't crash when running. The id may get deleted too early and you are only seeing issue when you step through slowly. – jdweng Oct 29 '20 at 18:14
  • Right, I think I understand the problem, just not sure how to solve it. If there was a PreNavigate in the Blazor life cycle I could solve it there – Tom Crosman Oct 29 '20 at 18:15
  • I think the issue is in the Java Dispose method. You have an Async method that needs an await. – jdweng Oct 29 '20 at 21:05
  • But the dispose from IDisposable isn’t async... – Tom Crosman Oct 29 '20 at 21:06
  • What about this : jsRuntime.InvokeAsync – jdweng Oct 29 '20 at 21:18
  • I am using Async, the method itself shows up as null (again, only when manually navigating does the error happen, internal side navigation it disposes properly. – Tom Crosman Oct 29 '20 at 21:26
  • Async is not going to wait and continue executing. – jdweng Oct 29 '20 at 21:29
  • I understand, I’m using the await. The interop file is not there when it tries. – Tom Crosman Oct 29 '20 at 21:29
  • I think that confirm my suspicion that there is a race condition. Where did the interop file get removed? – jdweng Oct 29 '20 at 21:49
  • Looks like this is an open bug with microsoft: https://github.com/dotnet/aspnetcore/issues/26474 – Tom Crosman Oct 30 '20 at 19:24
  • I do not see the correlation between your issue and the link you provided. You have only one instance and just trying to delete. – jdweng Oct 30 '20 at 20:48
  • See [here](https://stackoverflow.com/q/74928714/9971404) for related issue and solutions. – lonix Dec 27 '22 at 23:14

1 Answers1

3

I was able to solve this by adding a render check property.

private bool firstRenderComplete;

I set it here:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        firstRenderComplete = true;
        DayPilotJsInterop = new DayPilotJsInterop(JavascriptRunTime, InstanceId);

        await DayPilotJsInterop.Initialize();
    }
}

and finally test it here:

public void Dispose()
{
    if(firstRenderComplete == true)
    {
        DayPilotJsInterop.Dispose();
    }

}
Tom Crosman
  • 1,137
  • 1
  • 12
  • 37