状态已更改/此。StateHasChanged 似乎对 Blazor 组件没有影响



我正在使用MudBrazor库开发.net5 Blazor WebApp。我正在尝试创建一个显示特定类别和类别页面的导航菜单。但由于有可能添加新的类别,或添加新的分类页面,当信息发生变化时,我需要刷新我的组件。当调用OnInitializedAsync()中的函数时,按预期渲染导航菜单没有问题。但当更新了应该渲染的任何信息后再次调用它时,该函数似乎不再执行预期的操作,即重新渲染组件。现在,最简单的解决方案可能是我可以简单地刷新整个页面。但这不是我想要的,因为还有其他逻辑需要在不受页面重新加载干扰的情况下继续运行。我的.rarzor文件如下所示:

@inject CategoryService categoryService
@inject CategoryPageService categoryPageService
@inherits LayoutComponentBase
<MudText Typo="Typo.h6" Class="px-4" Style="margin-bottom: 10px; margin-top: 10px; text-align:center">Categories</MudText>
<MudDivider />
<MudNavMenu Style="color:white">
@foreach (Category category in NavCategories)
{
@if(NavCategoryPages.Count > 0)
{
@foreach(CategoryPage categoryPage in NavCategoryPages)
{
@if(categoryPage.CategoryId == category.Id)
{
<MudNavGroup Title=@category.Name>
@foreach(CategoryPage categoryPage1 in NavCategoryPages.Where(c => c.CategoryId == category.Id))
{
<MudNavLink>@categoryPage1.PageName</MudNavLink>
}
</MudNavGroup>
}
else
{
<MudNavLink>@category.Name</MudNavLink> 
}
}
}
}
</MudNavMenu>
@code
{
private List<Category> NavCategories = new List<Category>();
private List<CategoryPage> NavCategoryPages = new List<CategoryPage>();
protected override async Task OnInitializedAsync()
{
await GetCategoriesNav(); //Function that should grab the new information from the database
}
public async Task GetCategoriesNav()
{
NavCategories = await categoryService.GetCategories();
NavCategoryPages = await categoryPageService.GetCategoryPages();
//This delay is to have enough time to view if the StateHasChanged has any effect on first call.
await Task.Delay(5000);
StateHasChanged();
}
}

我已经仔细检查了它们必须显示的所有值,它们相应地显示在调试中。如果你需要任何额外的信息,请毫不犹豫地询问。

第一个呼叫在:

  • 类别Selector.razor
protected override async Task OnInitializedAsync()
{
await GetCategoriesNav();
}

这个调用按预期渲染NavMenu。在那之后,唯一一次在其他地方调用它是在我编辑/添加类别时。这是在中完成的

  • 类别管理
//These 2 functions are called via a button.
async Task AddCategory()
{
Category thisCategory = new();
var param = new DialogParameters { ["category"] = thisCategory };
IDialogReference dialog = DialogService.Show<CategoryDialog>("Add Category", param);
DialogResult result = await dialog.Result;
if(!result.Cancelled)
{
GetCategories();
//if a category has succesfully been added, it calls the same method which also gets called in the "OnInitializedAsync()"
await GetCategoriesNav();
}
}

async Task EditCategory(Category category)
{
category = await categoryService.EditCategory(category);
var param = new DialogParameters { ["category"] = category };
var dialog = DialogService.Show<CategoryDialog>("Edit Category", param);
DialogResult result = await dialog.Result;
if (!result.Cancelled)
{
GetCategories();
//if a category has succesfully been edited, it calls the same method which also gets called in the "OnInitializedAsync()"
await GetCategoriesNav();
}
}

这里是调用它的唯一外部位置,但CategoryAdministration继承自Category选择器。

我假设您有一个管理页面CategoryAdmin.razor,其中包含用编辑器打开对话框的按钮-Category Dialog。

在该页面中,您有一个显示NavCategories的组件(我认为它名为NavCategoriesComponent(。

单击其中一个按钮并编辑/添加类别,但在退出对话框时,NavCategories组件中的列表不会更新。

您还有一个CategoryService,我假设它可以获得类别列表。

NavCategoriesComponent中,您的代码如下所示:

private List<Category> NavCategories = new List<Category>();
private List<CategoryPage> NavCategoryPages = new List<CategoryPage>();
//OnInit code
NavCategories = await categoryService.GetCategories();
NavCategoryPages = await categoryPageService.GetCategoryPages();
//not required
await Task.Delay(5000);

然后在您的主要组件中,您调用以下代码进行添加/编辑:

GetCategories();
//if a category has succesfully been edited, it calls the same method which also gets called in the "OnInitializedAsync()"
await GetCategoriesNav();

那么,您希望第二次调用更新哪个列表?NavCategoriesComponent中的列表是完全独立的。编辑后调用GetCategories((不会更新NavCategoriesComponent中的列表。只有在重新加载页面时才会发生这种情况。顾名思义,OnInitializedAsync只运行一次。

如果这是你的基本场景,那么:

  1. 您的List<CategoryList<CategoryPage>列表需要位于CategoryService中。现在只有一个版本的真相
  2. 当您需要填充该列表时,请致电await categoryService.GetCategories()获取该列表
  3. 直接在NavCategoriesComponent中使用列表
  4. 添加一个event,比如RecordListChangedCategoryService
  5. NavCategoriesComponent中为该事件注册一个事件处理程序,并对该事件调用StateHasChaged
  6. 每当你"创建/更新/删除";在模式对话框中,更新CategoryService列表并触发RecordListChanged事件

您永远不应该手动调用OnInitializedAsync,也应该很少需要调用StateHasChanged

这个Github Repo包含一个解决方案,它在旧的Blazor WeatherReport应用程序Blazr.Demo.DB通知中演示了上述原理

等待启用StatehasChanged((的效果。所以改变顺序。

//await Task.Delay(5000);
StateHasChanged();
await Task.Delay(5000);

我读了很多关于为什么我的组件在从signalR获得更新的数据后没有渲染的文章,所以,无论他们说什么,都调用StateHasChanged((,但它不起作用。多亏了Brian Parker和Curtis的回答,我找到了对我有效的方法:用InvokeAsync调用StateHasChanged,如下所示:

InvokeAsync(StateHasChanged)

看看这个文件的第32行,它是这样调用的:FetchData.razor

相关内容

  • 没有找到相关文章

最新更新