Description
Consider the following scenario which is quite common:
A page with a grid with a pager. The grid loads data with an AJAX call and while the data is being loaded displays a loader. It is desirable that the data is displayed prerendered when using Blazor prerendering. Currently the most straight-forward implementation of this scenario works like this
- component lifecycle starts on the server
- a call is made to the service to get the page of data
- the data is prerendered and the component html is sent to the browser
- the browser renders the html. The user sees the data
- the component lifecycle starts on the client. The component makes a call to the service for a page of data. The data on the screen is replaced with a loader because according to the component on the client the data is null and a loader should be displayed while the call finishes.
- the call finishes and the data appears again
To sum it up the user sees data - loader - data. In addition two calls are made to get the data. The first issue can be mitigated by additional flags checking if we're in a first load situation on the client but it complicates the code significantly and it won't solve the second issue.
For me the additional complexity introduced by this issue was enough to turn off prerendering in my Blazor app. Maybe there is an easy workaround that I am not aware of but when I bring this issue up nobody has suggested a solution yet. The docs also seem to advise that we use caching but I don't consider this good enough as it will not remove the issue with the additional calls in Blazor wasm scenarios and still results in additional complexity.
Possible Solution
One solution I can think of is to mark certain component state with attributes and have that state be serialized while prerendering maybe as JSON and dump it into a hidden element on the page. Then when Blazor starts on the client it can read that state and initialize the component with it. This will avoid the second call for data and will simplify the code in the component.
Note that this issue is present with Blazor Server as well but with Blazor Server different approaches can be used like storing the whole component in memory and passing it upon the instantiation of the SignalR connection