Reputation: 1328
I have been playing with Blazor and trying to build a simple application. One of the first things I tried to do was to load data asynchronously (in my case from LocalStorage).
protected override async Task OnInitAsync()
{
await Log.Log($"{nameof(IndexComponent)}.{nameof(OnInitAsync)}");
Model = await LocalStorage.GetItem<DataModel>("model");
}
My rendering code looked like this:
<div>@Model.Attribute</div>
I was getting a NullReferenceException when rendering the page, plus the browser went into an unresponsive state at which point all I could was to close the browser tab and restart the Blazor application.
Even though it turned out this behaviour is by-design, I haven't found it explained on any piece of documentation and I think it's unexpected enough to grant sharing here. Hopefully it will help someone else (see my own answer below).
Upvotes: 9
Views: 7149
Reputation: 1328
It all boils down to:
Blazor calls your OnInitAsync method and renders your page first time immediately after first suspension (await). Then it renders your page again when your method finishes.
There are two solutions. The first one is to make sure your rendering code handles the case in which Model is null. So, instead of:
<div>@Model.Attribute</div>
use:
<div>@Model?.Attribute</div>
which would generate an empty div, or
@if (Model != null)
{
<div>@Model.Attribute</div>
}
which does not generate the div at all.
The other, simpler, solution is to make sure Model is never null:
protected DataModel Model { get; } = new DataModel();
Initially I raised an issue in Blazor's GitHub, from where I copied the answer almost verbatim: https://github.com/aspnet/Blazor/issues/1703
Very helpful members of the community very quickly pointed out what the issue was, and all the credit goes to them. I'm just trying to help other people by bringing the knowledge to StackOverflow.
Upvotes: 15