首页 > 解决方案 > 如何让参数不仅显示在组件中,而且在 OnInitializedAsync() 中被识别?

问题描述

我正在开发一个 blazor 服务器端项目,并且我有一个组件将模型(pickedWeek)作为参数传递。我可以很好地使用与 html 一致的模型,但 OnInitializedAsync 始终认为模型为空。

我已将本机类型作为参数从页面传递到组件中,这样没有问题。我使用 NullWeek 作为默认参数,因此在 OnInitializedAsync 中使用的数字似乎只来自 NullWeek。如果这是相关的,则有一个兄弟组件通过 .InvokeAsync 调用将 Week 模型返回到 Page,其中 StateHasChanged() 在更新后被调用。似乎新的 Week 正在更新问题组件,但 OnInitializeAsync() 要么看不到它,要么永远不会再次触发 - 这可能是我的问题,但我认为它不是那样工作的。

例如,下面的代码将始终显示“FAILURE”,但它会显示正确的 Week.Number。下面的代码:

<div>@pickedWeek.Number</div>
@if(dataFromService != null)
{
    <div>SUCCESS</div>
}
else
{
    <div>FAILURE</div>
}

@code{
    [Parameter]
    public Week pickedWeek { get; set; }
    protected IEnumerable<AnotherModel> dataFromService { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (pickedWeek.Number > 0)
        {
             dataFromService = await _injectedService.MakeACall(pickedWeek.Id);
        }
    }
}

标签: componentsblazor-server-side

解决方案


@robsta 在评论中有这个正确的,你可以使用OnParametersSet它。然后,您将遇到另一个问题,因为每次重新渲染都会再次设置您的参数并生成对您的服务的另一个调用。我已经通过使用标志字段和OnParametersSet方法来解决这个问题。试一试,然后报告。

private bool firstRender = true;

protected override async Task OnParametersSetAsync()
{
    if (pickedWeek.Number > 0 && firstRender)
    {
        dataFromService = await _injectedService.MakeACall(pickedWeek.Id);
        firstRender = false;

        // MAYBE call this if it doesn't work without
        StateHasChanged();
    }
}

Another alternative is to use the OnAfterRender override, which supplies a firstRender bool in the the method signature, and you can do similar logic. I tend to prefer the first way though, as this second way allows it to render, THEN sets the value of your list, THEN causes another rerender, which seems like more chatter than is needed to me. However if your task is long running, use this second version and build up a loading message to display while the list is null, and another to display if the service call fails. "FAILURE" is a bit misleading as you have it as it's being displayed before the call completes.

I've also found that a call to await Task.Delay(1); placed before your service call can be useful in that it breaks the UI thread loose from the service call awaiter and allows your app to render in a loading state until the data comes back.


推荐阅读