GH DevOps
GH DevOps

Reputation: 426

Blazor .NET 8 web app - PersistentComponentState with per-page rendering

I have a .NET 8 Blazor web app that uses per-page rendering (nothing set globally) which renders my nav bar and main layout statically on the server. I navigate to a razor component page that sets the render mode at the component level (@rendermode InteractiveWebAssembly). If I try to use PersistentComponentState inside OnInitializedAsync(), I get the following error:

InvalidOperationException: The registered callback b__0 must be associated with a component or define an explicit render mode type during registration.

How do I explicitly register my component state when navigating to my component from a statically rendered parent?

If I set the render mode globally in App.razor, my code works fine. I'd prefer to per-page rendering but I want to be able to handle the pre-render correctly without calling my database twice.

Here's my navlink:

<AuthorizeView>
    <Authorized>                
        <div class="nav-item px-3">
            <NavLink class="nav-link" href="map">                        
                <span class="bi bi-map-fill-nav-menu" aria-hidden="true"></span> Map                        
            </NavLink>
        </div>
    </Authorized>            
</AuthorizeView>

My component:

@inject PersistentComponentState ApplicationState
@rendermode InteractiveWebAssembly
...
@code {
   private PersistingComponentStateSubscription subscription;
   ...

protected override async Task OnInitializedAsync()
{    
    cts = new CancellationTokenSource();

    subscription = ApplicationState.RegisterOnPersisting(() =>
    {
        ApplicationState.PersistAsJson("MapInit", MapInitialization);
        return Task.CompletedTask;
    });

    if (ApplicationState.TryTakeFromJson("MapInit", out MapInitialization? storedData))
    {
        MapInitialization = storedData;
    }
    else
    {
        MapInitialization = await GrsService.GetMapInitialization(cts.Token);

        if (MapInitialization is not null)
        {
            MapInitialization.Plants = await GrsService.GetPlants(MapInitialization.MapSettings?.VisiblePlants, cts.Token);

        }
    }
    ...
}

}

Upvotes: 1

Views: 779

Answers (1)

GH DevOps
GH DevOps

Reputation: 426

There's an IComponentRenderMode parameter inside the RegisterOnPersisting() method that gives you the ability to set the rendermode per subscription:

subscription = ApplicationState.RegisterOnPersisting(() =>
{
    ApplicationState.PersistAsJson("MapInit", MapInitialization);
    return Task.CompletedTask;
}, RenderMode.InteractiveWebAssembly);

Upvotes: 0

Related Questions