gpt4 book ai didi

c# - StateHasChanged() 重新渲染组件两次

转载 作者:行者123 更新时间:2023-12-03 14:37:05 24 4
gpt4 key购买 nike

我正在制作一个 Blazor 服务器端项目,我想制作一个点击后停用的按钮,但不使用 disabled <button> 的属性.代码非常简单:

@functions {

LogInForm logInForm = new LogInForm();
bool IsDisabled;
SignInResult result;

protected override void OnInitialized()
{
IsDisabled = false;
}

async Task TryLogIn()
{
IsDisabled = true;
StateHasChanged();
result = await _LogInService.TryLogIn(logInForm);
Console.WriteLine("Logging status : " + (result.Succeeded ? "Sucess" : "Failure"));
IsDisabled = false;
StateHasChanged();
}

}

出于奇怪的原因,第一个 StateHasChanged没有触发,但第二个确实重新呈现页面。通过进入 Debug模式并进入 StateHasChanged(),它可以很容易地进行测试。方法。第二次调用时,它会在进入方法后停止在 HTML 代码上,但不是第一次。

为什么这样 ?

注意:我不是在寻找任何使用 Task.Delay 的解决方法或 Task.Run(...)只是,因为它在这些线程和 UI 刷新线程之间存在竞争条件,所以它不是一个可靠的解决方案。我在 StateHasChanged() 上寻找答案通过使用诸如 PropertyChanged 之类的事件的行为或解决方法或 EventCallback并将按钮作为子组件。

编辑:经过一些测试,似乎 StateHasChanged()仅在 await 之后触发组件的重新渲染对 Task 的操作.可以通过添加评论来轻松测试 result = await _LogInService.TryLogIn(logInForm);线或改变 IsDisabled = ...await new Task.Run(() => { IsDisabled = ...}) .我现在有一些解决方法,但我仍然想知道为什么这是一个功能。不应该 StateHasChanged()任何操作后重新渲染?或者认为只有 async操作(因此主要是服务器调用)可以更改 UI 中的某些内容?

最佳答案

Blazor 团队即将发布有关 StateHasChanged() 工作原理的文档。

你可以在这里跟踪它:https://github.com/aspnet/AspNetCore/issues/14591

就目前而言,我认为摘自 github 评论的这个解释是一个很好的解释:

Adding a call to StateHasChanged simply queues the component to be rendered. The renderer decides when the renders happen.

This can be triggered by 4 circumstances:

  • Initial render where the bootstrap process triggers the initial render of the root component and all its children.
  • An event, in which the component that handles the event automatically triggers a new render after the event, and potentially its children if it renders new children or change their parameters.
  • As a result of calling StateHasChanged from an InvokeAsync call (marshalling back into the UI thread, essentially)
  • As a result of the parent component changing the parameters for the child component, which happens as part of the diffing process when the renderer calls SetParametersAsync on the child component.

To be very clear, calling StateHasChanged only queues a Render for the component or "marks it as dirty".

It's the renderer the one that decides when and how to produce the renders. BuildRenderTree does not result in new rendered output, only in a new definition of the "V-DOM" for the component at the time it's being called.

Normally, a component gets rendered once per render batch (which is a collection of components that are rendered/diffed together and sent to the UI for update). There are only two situations in which a component renders more than once in a batch:

  • You have a component that directly implements IComponent and calls RenderHandle.Render
  • You have a circular dependency between a child and a parent component that might cause a parent to re-render as part of a children invoking some callback parameter from the parent as part of its initialization


来源: https://github.com/aspnet/AspNetCore/issues/15175#issuecomment-544890549

关于c# - StateHasChanged() 重新渲染组件两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58932854/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com