Blazor父组件在子组件的onclick事件后意外重新初始化

3

那么,在Blazor Server应用程序中,我有一个父组件和一个子组件。父组件在index.razor页面中,不需要任何参数。子组件有一个列表作为参数:

...
@if (People == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <li>

    @foreach (var p in People)
    {
        <ul>@p.LastName, @p.FirstName</ul>
    }
    </li>
}

@code {
    [Parameter]
    public IReadOnlyList<PersonModel> People { get; set; }
}
...

在父组件中,有一个表单和一个按钮,点击按钮会执行某些操作并构建一个列表,然后将这个列表作为参数传递给子组件。
...
<button class="btn btn-outline-primary" type="submit" @onclick="(() => SearchPeople(firstNameInput, lastNameInput))">Search</button>

...
        @if(peopleResults != null)
        {
            <PeopleList People="peopleResults"></PeopleList>
        }

@code {

    private string lastNameInput = string.Empty;
    private string firstNameInput = string.Empty;

    private List<PersonModel> peopleResults {
        get;
        set; }

    private async Task SearchPeople(string lastName, string firstName)
    {
        peopleResults = await _personData.SearchPeopleByName(firstName, lastName);
    }

}

SearchPeople方法工作正常并返回正确的数据。我已经调试了程序,看起来它确实开始正确地构建带有List子组件。事实上,在某些情况下,我曾经看到它在页面上出现了一秒钟。但是,在此之后,父组件完全重新初始化,并且所有属性都被重置为默认值。我放置了一个

protected async override Task OnInitializedAsync() {
}

在父组件中调用的方法,以及在该方法中设置了断点,确实会在单击事件之后的某个时间点被调用。因此,每次单击按钮时,父组件肯定会被清除并重新初始化。

我的问题是,为什么Blazor要重新初始化父组件呢? 我遵循了这篇帖子的建议,但不确定我做了什么不同:如何在Blazor中将List<string>作为参数传递给子组件?

我认为可能是因为我将一个可变参数传递给了子组件,如果子组件对其进行了修改,Blazor可能会认为应该重新初始化父组件,但是这个参数存在于父组件中,所以这是没有意义的。

3个回答

4
你有一个隐藏的 async void,因此重新渲染不同步。

更改这一行

<button class="btn btn-outline-primary" type="submit" 
  @onclick="(() => SearchPeople(firstNameInput, lastNameInput))">Search</button>

to:

<button class="btn btn-outline-primary" type="submit" 
  @onclick="(async () => await SearchPeople(firstNameInput, lastNameInput))">Search</button>

你可能需要在那里使用 type="button",这不是主要问题。


当你处理像@onclick这样的用户事件时,Blazor会在处理程序后进行隐式的StateHasChanged(),导致页面重新渲染。

SearchPeople()是一个异步方法,但在原始事件处理程序中没有await。因此,它以触发并忘记的方式运行,并且在方法完成之前重新呈现。


就是这样了!现在运行得很好。谢谢!所以,为了更清楚地向自己解释,没有等待任务,因此主线程继续执行,导致空列表? - Zachary Quinn
主线程在SearchPeople()完成之前(因为@onclick)更新了屏幕。 - H H

1

我想你的父组件在一个 EditForm 内,并且你正在更改它的 Model 参数。这会导致其中所有的组件被销毁并重新创建。


0

我在一个表单中有一个按钮,它有一个OnClick事件调用了一个空方法--是的,它什么也没做。点击按钮会导致整个页面重新初始化以及所有组件,而且无论我尝试什么都无法阻止这种行为。解决方案就是简单地摆脱表单标签。

这是Blazor处理表单的一个奇怪的警告。

建议:除非您的实现绝对需要,否则不要使用表单。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接