【问题标题】:Calling StateHasChanged vs returning Task调用 StateHasChanged 与返回 Task
【发布时间】:2021-04-29 22:30:49
【问题描述】:

我正在使用 Blazor Web 程序集项目的基本模板。我试图了解似乎达到相同结果的两种不同方法的情况。

在我的第一次尝试中,我创建了一个方法,将新的 WeatherForecast 模型发布到我的 Web api 端点,然后从响应中,将新创建的 WeatherForecast 添加到列表中。这是第一种方法:

private async void ValidSubmitHandler()
{
    var response = await Http.PostAsJsonAsync<WeatherForecast>(Configuration["APIBaseUrl"] + "/WeatherForecast", newForecast);

    var forecast = await response.Content.ReadFromJsonAsync<WeatherForecast>();
    forecasts.Add(forecast);
}

我原以为 UI 会使用新添加的预测进行更新,但尽管预测列表添加了新对象,但页面并未更新。我设置了一个断点并观察到新的预测确实已添加到列表中,但只是 UI 没有将更改呈现到列表的状态。

我知道你可以打电话

StateHasChanged() 

启动更改以呈现列表的新预测,目前这很好。在阅读了一些关于 StateHasChanged 的​​信息之后,似乎我不应该经常使用它,它会显示出不良做法的迹象,所以我尝试了一位同事的建议,他说我需要添加 Task 作为返回类型而不是 void 到像这样的功能:

private async Task ValidSubmitHandler()
{
    var response = await Http.PostAsJsonAsync<WeatherForecast>(Configuration["APIBaseUrl"] + "/WeatherForecast", newForecast);

    var forecast = await response.Content.ReadFromJsonAsync<WeatherForecast>();
    forecasts.Add(forecast);
}

这确实允许 UI 接收更新,我只能假设 ValidSubmitHandler() 在新预测添加到列表之前退出。

如果我的方法没有等待异步操作的结果,是否有人解释为什么 StateHasChanged 似乎有效?

谢谢

【问题讨论】:

    标签: c# .net async-await blazor-webassembly


    【解决方案1】:

    当事件处理程序完成时,Blazor 会自动调用 StateHasChanged。以下是来自 GitHub 的相关代码:

        // https://github.com/dotnet/aspnetcore/blob/547de595414d6ebb9ddeaa4a231815449c9f3c60/src/Components/Components/src/ComponentBase.cs#L301
        Task IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, object? arg)
        {
            var task = callback.InvokeAsync(arg);
            var shouldAwaitTask = task.Status != TaskStatus.RanToCompletion &&
                task.Status != TaskStatus.Canceled;
    
            // After each event, we synchronously re-render (unless !ShouldRender())
            // This just saves the developer the trouble of putting "StateHasChanged();"
            // at the end of every event callback.
            StateHasChanged();
    
            return shouldAwaitTask ?
                CallStateHasChangedOnAsyncCompletion(task) :
                Task.CompletedTask;
        }
    

    Blazor 等待事件处理程序返回。然后,它调用StateHasChanged。如果返回的Task没有完成,则等待该任务并再次调用StateHasChanged

    async void的情况下,返回的任务总是完成的,所以它永远不会等待它并调用第二个StateHasChanged。在这种情况下,您需要手动调用它。但更好的方法是避免async void,这几乎总是一件坏事。

    我还写了一篇关于组件生命周期的更深入的博文ASP.NET Core Blazor components lifecycle

    【讨论】:

    • 这是您在链接中的一个很好的简单解释,那里。干得好!
    猜你喜欢
    • 2021-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多