Closed CaveRock closed 9 months ago
@CaveRock thanks for contacting us.
We'll take a look and update this issue.
@mkArtak parking this in 8.x as if it repro's it's a patch candidate
I am also experiencing this.
Hi, thanks for reaching out!
There seems to be a small misconception here. In the FormProblem
component in the repro you provided, there's the following code:
<h3>FormProblem @(OperatingSystem.IsBrowser() ? "WASM" : "SERVER")</h3>
This line implies that there are two possible states for the component to be in, but there are actually three:
The code in FormProblem
conflates the first two cases. You'll notice that even if you change the render mode of the page to InteractiveWebAssembly
, the bug seems to appear. That's because the transition you're experiencing is from "prerendered" to "WebAssembly interactive", not from "Server interactive" to "WebAssembly interactive". The Auto render mode never changes the interactive render mode of an existing component.
The problem you're likely experiencing is https://github.com/dotnet/aspnetcore/issues/42561, which tracks improving the transition from "prerendered" to "interactive".
If you want a component that correctly indicates what the current render mode is, something like this should work:
<p>Render mode: @renderMode</p>
@code {
private string renderMode = "SSR (not interactive)";
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
renderMode = OperatingSystem.IsBrowser() ? "WebAssembly interactive" : "Server interactive";
StateHasChanged();
}
}
}
Hope this helps! Closing out this issue as a dupe of #42561.
@MackinnonBuck thanks for the feedback.
I think there is still an issue here, did you watch the video I attached? The issue is that the server rendered component is being swapped out with a wasm version whilst the user is still interacting with the component which is wiping the state. I only placed:
<h3>FormProblem @(OperatingSystem.IsBrowser() ? "WASM" : "SERVER")</h3>
so that one can see this swap occurring along with the entire form state being wiped. I do understand the pre-render is a '3rd' state, the pre-render is not the issue, the swap from server to wasm is the issue.
My issue is really apparent when using a slow connection, which is common where I am, and any interaction by the user with the form will be wiped as soon as the wasm binaries download completes, whereas the wasm version should only be used the next time the user navigates to the form component. In order to really see this one needs to use browser dev tools to throttle connection to "slow 3g'.
I may still be miss-understanding and apologise if that is the case, but would appreciate if we could just make sure we are both viewing this from the same 'lense'.
Thanks
Hi @CaveRock,
I understand what you're saying and have seen your video (and tested your repro to make sure I'm not missing anything else), and I believe what I said in my previous comment is accurate. I appreciate there is a problem here that can create the bad UX you're seeing, so I'll do my best to clarify what's happening.
The issue is that the server rendered component is being swapped out with a wasm version whilst the user is still interacting with the component which is wiping the state... the pre-render is not the issue, the swap from server to wasm is the issue.
It's not swapping from server to wasm interactivity. Even though it might appear this way, the line of code in your example does not indicate the interactive render mode. If you remove the @rendermode
from the page, "SERVER" will still get rendered even though the page is not interactive. Therefore, the component displaying "SERVER" is not an indication that the component is using server interactivity. It actually means that either:
I believe your repro demonstrates the former. Note that interactivity isn't required for the user to start entering text into the text input - the user can do that on a non-interactive page, as they could on a plain HTML input element.
I'm not trying to suggest that there isn't a problem here (as many developers have indicated being affected by this in #42561). I'm trying to say that the problem might not be what's reported in this issue.
To demonstrate what I'm saying, could you please try the following? Change the render mode on the FormProblem
component to InteractiveWebAssembly
. I think you'll find that the problem still appears. You could also check the network tab in the browser dev tools window and observe that despite this transition, no Blazor Server websocket connection was opened. See also the code I pasted in my last comment, since that will help correctly distinguish between the 3 render modes.
One potential workaround is to initially render the page with the input elements disabled, then enable them after the component becomes interactive. This will prevent the user from entering text that gets wiped after the transition to interactivity.
Hope this helps.
@MackinnonBuck thanks for the detailed response.
Something that could help me understand what is considered statically rendered vs interactive, if the initial form that loads is able to produce form validation messages based on the attributes placed on the form model properties when hitting the submit button with invalid inputs, would that be considered that the render is achieved "interactivity"?
I ask as I have another repo that I can show the initial load, I can interact with the form, hit the submit button and get all the expected validation errors, then a couple seconds later (when I assume the wasm download completes) the form is wiped, all inputs reset and all validation state reset. This to me feels like interactive and not the initial static render.
If you agree then I will put together a new repo that demonstrates this behaviour.
@CaveRock in the case you just described, the validation messages are being displayed because they were included in the server's response HTML after the form post. If you were to make the page non-interactive, the validation messages should still show up in the same way.
An interactive form would show validation messages immediately after an input element loses focus, even before the form gets submitted.
Interactive functionality is that which can apply updates to the existing page without requesting new page content from the server. i.e., if a component's logic runs using WebAssembly, or if requires a Blazor Server circuit, it's considered to be interactive.
Is there an existing issue for this?
Describe the bug
RenderMode Auto does not wait to replace Server Interactive mode with WasmInteractive until next use of component, it does it as soon as wasm has downloaded. Any user interaction with the component, like entering text into an input element, is wiped when the component is replaced while user is still interacting with the component.
Expected Behavior
The expected behavior is that the component will load initially as server interactive and then stay as server interactive until the next time the component is used.
Steps To Reproduce
Set component to use RenderMode Auto, for example an Input Form. Set browser dev tools to replicate 3g connection in order to see the issue more easily. Run Application. Click Form Problem Nav Link. Cntrl F5 to hard refresh to ensure Server Interactive mode initially. On first load of the input form component it will load as server interactive as expected, however, as soon as WASM has downloaded the component is swapped out immediately. User can type into the Input Form while it is Server Interactive, but the component will be completely replaced as soon as WASM version of component is available, this wipes all user input from the form.
Attached video of the issue demonstrated with a Form
https://github.com/dotnet/aspnetcore/assets/4638922/e600b181-2174-463a-9aec-32e4f8484722
Repo to reproduce
Additional example with different behavior can be seen with Counter component in the linked repo.
Cntrl F5 refresh while on the Counter component, attempt to interact with Click Me button. There will be no increment until the Server Interactive version of the component has been replaced with the wasm component, this replacement will happen without having to navigate away from the component.
Exceptions (if any)
No response
.NET Version
8
Anything else?
No response