我试图弄清楚单击按钮后如何刷新客户端组件。
回购链接,例如: https://github.com/ovie91/RefreshComponent
站点/测试或从导航菜单测试
所以我有从API检索数据的OnInitializedAsync方法
protected override async Task OnInitializedAsync()
{
result = await (some API Call);
}
然后我有一个连接到按钮的方法
private async void ButtonClick()
{
await (some API Call);
result = null;
this.StateHasChanged(); <--- Doesnt work :<
}
我尝试使用 this.StateHasChanged(); ,但没有反应。 解决方法是,我可以强迫您再次导航到同一网站,但此刷新的是“整个”网站,而不是组件。
关于如何处理它的任何想法?
整个代码(最小化):
@page "/test"
@inject HttpClient Http
@if (result == null)
{
<p>Loading...<p>
}
else
{
@result
<button @onclick="(() => ButtonClick())">Click</button>
}
@code {
private APIObject result;
protected override async Task OnInitializedAsync()
{
result = await (some API Call);
}
private async void ButtonClick()
{
await (some API Call);
result = null;
this.StateHasChanged(); <--- Doesnt work :<
}
}
更新 我想刷新组件,以便OnInitializedAsync会再次被触发,这意味着单击按钮后不必再次运行相同的代码。希望你明白我的意思。
答案 0 :(得分:2)
要获得所需的输出,您只需从以下位置稍微拖尾几行即可:
private async void ButtonClick()
{
await (some API Call);
result = null;
this.StateHasChanged(); <--- Doesnt work :<
}
收件人:
private async void ButtonClick()
{
result = null;
this.StateHasChanged(); // should show '<h3>Loading</h3>' now
await (some API Call);
}
但是,从您的回答中我们会得到
var APICall = await Http.GetAsync("SomeAPI");
Thread.Sleep(2000);
当Http.GetAsync("SomeAPI");
确实是一个异步调用,而不仅仅是一些替代的伪代码时,这应该起作用。因为Thread.Sleep(2000);
会冻结一切。
如果要确保:
private async Task GetData()
{
await Task.Yield(); // release the thread for rendering
var APICall = await Http.GetAsync("SomeAPI");
Random rnd = new Random();
Thread.Sleep(2000); // Task.Delay() is much preferred
result = "Random Number: " + rnd.Next();
}
Thread.Sleep()
适用于模拟某些占用大量CPU(而非I / O)的代码。因此,我并不是说这是错误的,而是要注意区别。
使用事件处理程序async Task
代替async void
更好,但这不是这里的直接问题。
答案 1 :(得分:1)
来自here:
Blazor使用同步上下文(SynchronizationContext)强制执行单个逻辑线程。在同步上下文中执行组件的生命周期方法以及Blazor引发的任何事件回调。
Blazor Server的同步上下文尝试模拟单线程环境,以使其与浏览器中的WebAssembly模型紧密匹配,该模型是单线程的。在任何给定的时间点,工作都只在一个线程上执行,给人以单个逻辑线程的印象。没有两个操作可以同时执行。
因此,作为 enet asnwered,您应该使用let key = 'your key'; // I suppose you generate the key programatically
this.sample[key] = [{first: "", second: ""}];
签名而不是async Task
。
答案 2 :(得分:-1)
我已将API调用移至另一个方法,并在我调用它的OnInitializedAsync内部。
然后,当我重置结果变量以查看加载状态时,我能够“刷新”组件以实现您需要添加的组件。 this.StateHasChanged()
现在我有一个响应组件来响应正在发生的更新:)
@page "/test"
@using System.Threading;
@inject HttpClient Http
@if (result == null)
{
<h3>Loading</h3>
}
else
{
@result
<button @onclick="(() => ButtonClick())">Click</button>
}
@code {
private string result;
protected override async Task OnInitializedAsync()
{
await GetData();
}
private async Task GetData()
{
var APICall = await Http.GetAsync("SomeAPI");
Random rnd = new Random();
Thread.Sleep(2000);
result = "Random Number: " + rnd.Next();
}
private async Task ButtonClick()
{
await Http.GetAsync("SomeAPIcall");
result = null; // required to see loading state.
this.StateHasChanged(); // when added model is refreshed and Loading state is visible.
await GetData();
}
}