使用 http post 并在 Blazor 中设置 class 时出现奇怪和意外的行为。为什么?

Weird and unexpected behaviour while using http post and set a class in Blazor. Why?

这是一个非常简单的登录屏幕...

@inject HttpClient Http
@inject User user
@page "/loginSignup"
<div class="text-center">
Logged: [@user.Name]

    <EditForm class="form-signin" model="@loginForm" OnSubmit="@DoLogin">
        <img class="mb-4" src="https://getbootstrap.com/docs/4.0/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72">
        <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
        <label for="inputEmail" class="sr-only">Email address</label>
        <InputText @bind-Value="loginForm.email" type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus />
        <label for="inputPassword" class="sr-only">Password</label>
        <InputText @bind-Value="loginForm.password" type="password" id="inputPassword" class="form-control" placeholder="Password" required />
        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
        <p class="mt-5 mb-3 text-muted">
            <a @onclick='() => mode ="signup"' @onclick:preventDefault href="">Not registered ? Create an Account</a>
        </p>
    </EditForm>
</div>

@code {
    private string mode = "login";
    public LoginFormModel loginForm = new LoginFormModel();

    private async void DoLogin()
    {
        var body = new LoginFormModel { email = loginForm.email, password = loginForm.password };
        var response = await Http.PostAsJsonAsync("http://localhost:1337/customers/login", body);
        User userSet = await response.Content.ReadFromJsonAsync<User>();
        user.Name = "tst";
        Console.WriteLine(user.Name);
    }

    public class LoginFormModel
    {
        public string email { get; set; }
        public string password { get; set; }
    }
}

当我提交时,html 上的 Logged: [@user.Name] 行不会显示任何内容,但控制台会显示 tst。如果我再次按下提交,它会按预期工作,这将在 Logged: [@user.Name] 和控制台上显示 TST。

我决定在 DoLogin 评论所有的行然后就离开了:

user.Name = "tst";
Console.WriteLine(user.Name);

以这种方式,这按预期工作。如果我按下提交,我可以在控制台和屏幕上看到 Tst。这意味着我的 http 调用以某种方式弄乱了渲染。为什么?

更多详情:

Core5,注入的用户是单例class。

问题是由您的异步方法的 return 类型引起的:您 return 一个 void 是非阻塞的。 The docs about this topic

非阻塞意味着调用者不会等待完成调用并立即继续下一个语句。 IE。在这种情况下,渲染引擎可能会在 DoLogin 仍然是 运行 且输出值尚未设置时触发组件更新。

要正确使用 await/async,您需要 return 方法中的等待任务。


旧答案(不再完全有效):

(我认为)问题是你更新了一个外部(注入的)对象。因此 Razor 组件实例将不会检测到任何内容在本地更新并且不会刷新。

我认为最好的解决方案是用局部变量替换名称

Logged: [UserName]

...
@code{
    private string UserName {get;set;}
...
    private async Task DoLogin()
    {
        ...
        UserName = "tst"; // or =user.Name;
    }    
}

另一种方法是使用 await InvokeAsync(StateHasChanged);

触发组件更新