Blazor 组件未在状态变化时调用 OnInitializedAsync,已链接 data-fetching

Blazor component not calling OnInitializedAsync on statechange, chained data-fetching

我是 blazor 的新手,仍在学习,我的仪表板有一个 state-problem。

我有一个组件可以获取仪表板和面板:

@if (Data == null)
{
    <Loader></Loader>
    return;
}
<Row NoGutters="true">
    @foreach (var panel in Data.Panels)
    {
        <Column XS="12" SM="12" MD="6" LG="6" XL="4" Class="mb-4">
            <CascadingValue Value="@panel.Id">
                <DashboardMatare DateHeader="@panel.DateHeader" Header="@panel.Header" ></DashboardMatare>
            </CascadingValue>
        </Column>
    }
</Row>

它通过 OnParametersSetAsync 获取数据并且工作正常,它获取新面板并呈现它们

但是当我切换到另一个仪表板时,“DashboardMatareChartJs”的前一个仪表板的相同值仍然存在。

如果仪表板之间的面板数量不同,它将呈现新面板。

我将 panelId 级联到 children,这样 blazor 就会知道它需要更改状态。

仪表板资料:

<DashboardContainer>

<DashboardHeader Header="@Header" DateHeader="@DateHeader"></DashboardHeader>

<CascadingValue Value=PanelId>
    <DashboardMatareChartJs />
</CascadingValue>

DashboardMatareChartJs:

if (Data == null)
{
    <Loader />
    return;
}

<div class="pl-3">
    <Row NoGutters="true" Class="h-75">
        <Column Class="col-12">
            <div class="matare">
                <div class="valueWrapper">
                    <canvas class="meterGraph" ref="ReferenceToChartJs">
                    </canvas>
                </div>
            </div>
        </Column>
    </Row>
    <Row>
        <Column Class="text-left col-12">
            <DashboardJamforMed JamforMedText="Data.JamforMedText" IsProcent="Data.ShowPercentage"></DashboardJamforMed>
        </Column>
    </Row>
</div>


[Inject]
protected HttpClient HttpClient { get; set; }

[CascadingParameter]
public Guid PanelId { get; set; }

public ElementReference ReferenceToChartJs { get; set; }

[Inject]
private IJSRuntime JsRuntime { get; set; }

public DashboardPanelGraphDataDto Data { get; set; }

protected override async Task OnInitializedAsync()
{
    Data = await HttpClient.GetFromJsonAsync<DashboardPanelGraphDataDto>($"api/DashboardBlazor/GetChartData/{PanelId}");
}

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (Data == null || ReferenceToChartJs.Context == null)
    {
        return;
    }

    await JsRuntime.InvokeVoidAsync("chartService.drawGraph", ReferenceToChartJs, Data.ChartData, Data.TypeOfGraph, Data.ShowPercentage);
}

DashboardHeader 将始终具有正确的数据

问题似乎是组件在更改 PanelId 时不会调用 OnInitializedAsync。我认为这是一个结构问题,因为我试图通过@ref 强制 statehaschanged 并从 parent 调用 StateHasChanged,仍然不起作用。

如果我通过“DashboardMatareChartJs”上的 OnParametersSetAsync 获取数据,那么它会加载新数据,但它会加载几次,而且对于不在视图中的面板。我知道这意味着我可能还没有 100% 理解 blazor 的生命周期,所以希望有人能把我推向正确的方向。

提前致谢!

尝试使用@key 指令属性强制 Blazor 重建 DashboardMatare 对象,如下所示:

<DashboardMatare @key="@panel.Id" DateHeader="@panel.DateHeader" Header="@panel.Header" ></DashboardMatare>

此答案基于以下内容:

You can also use @key to prevent Blazor from preserving an element or component subtree when an object changes:

<div @key="currentPerson">
    ... content that depends on currentPerson ...
</div>

If @currentPerson changes, the @key attribute directive forces Blazor to discard the entire and its descendants and rebuild the subtree within the UI with new elements and components. This can be useful if you need to guarantee that no UI state is preserved when @currentPerson changes.

Link to Source...