-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Declarative model to serialize state on prerendering with Blazor and restore it on the client #26794
Comments
I was also put off by having to cache and write hacky code to avoid the FOOC effect when using prerendering. Indeed, even when the user does not see a flash, Blazor wasm still does unnecessary work as the actual data is being rendered twice. Referencing @jonhilt here because he demonstrated the "double rendering" in this scenario in a blog post two days ago: scroll down to OnInitializedAsync is called twice. |
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process. |
@mkArtakMSFT I don't know how React works and the issue doesn't explain the details but looking at the docs for React's hydrate() it seems like it is used to attach events not to restore state from the DOM |
The concept needed here is called SSR client side hydradation. Examples in js SSR land explained in the first paragraph of the links below: Issue #26802 should probably be deleted. |
@jotosmurf the links you provided talk about attaching events to existing HTML which is fine and great but how is the state of the component restored? If I have a |
@mkArtakMSFT @javiercn This issue duplicates #26802 in terms of what effect both authors want to achieve. |
It is great that we already have a solution for this in the latest preview but the solution seems too imperative and "manual". While having this as an option is fine I hope there will be a declarative and more transparent solution. I imagine something like marking a component with an attribute like [PreservesState] and then all the state preserving is done automatically and if the user does not want some field to be preserved they mark it with [NotPreserved] (might be good to exclude members marked with [Parameter]). Maybe even consider totally skipping the initialize event if the state has been restored declaratively. |
@javiercn Feedback from .NET 6 Preview 2 on state persistence. |
We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process. |
Thanks for contacting us. We're moving this issue to the |
Declarative support for persisted component stateGoalsEnable a way for state to be persisted declaratively as opposed to imperatively, as to make the feature more discoverable and easier to use. Challenges and constraintsThe main challenge that we have is that we essentially emit a dictionary to the output to support persisting the state, and each key needs to be unique. The imperative API allows you to "figure this out" by yourself to a degree, but a declarative API can't easily do so in some scenarios. Our goal is to generate a unique key for each usage of the feature. That mapping needs to be preserved when the app restarts interactively. There are also a couple scenarios we need to account for.
Generating a key for components.
Generating a key for services
APIThis will be a new In addition to this, there will also be a [PersistState] attribute for services that they can apply to properties to ensure that they get persisted, with an additional Mode property to specify where things need to be persisted. Once we enable persisted component state for enhanced navs, we'll need a UpdateOnEnhancedNavigation parameter to determine if the component wants to receive updates. Implementation detailsThis gets integrated as any other cascading value. When a component is rendered and contains the attributes, we register the persistence callback, when it gets removed from the dom we unregister the callback. We only register callbacks on the SSR, on wasm/server we don't. |
Is it possible to use the approach from web forms where the key is the ids of each of the parent components back to the root? I realize that Blazor components don't have explicit ID, but one could be generated in the background |
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
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
The text was updated successfully, but these errors were encountered: