简体   繁体   中英

Missing StateChange after changing a variable in async method

I try to show a spinner while loading the data. The spinner worked just fine, as long as i didn't explictly made all the calls asnyc. But since I change to async calls, it seems that the StateChanges of the two variable isLoading and emptyResult won't be recognized. Everything else just runs as it should and after a view seconds my the table is shown, but i never get the spinner. What am I missing here?

<EditForm Model="@parameter" OnValidSubmit="@Submit">
 
...
</EditForm>

@if (isLoading && !emptyResult)
{
    <div class="spinner"></div>
}
else if(!isLoading && emptyResult)
{
    <div>
        <span class="text-danger">
            No data for given parameters.
        </span>
    </div>
}
else if (data != null && !isLoading && !emptyResult)
{
    //Table of data
}


@code{
    private MyParameter parameter = new MyParameter();
    private List<CustomObject> data;

    private bool isLoading = false;
    private bool emptyResult = false;

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
    }

    private async Task Submit()
    {
        emptyResult = false;
        isLoading = true;
        await LoadDataAsync();
        isLoading = false;
    }
        
    private async Task LoadDataAsync() 
    {
       data = await service.GetData(parameter);
       if(data is null)
       {
           emptyResult = true;
       }
       else { 
       //Some calculation on data
       }
    }
 }
    

I took your page and made it standalone and added a bit more display logic. Here's my version which I think works as you want it to.

@page "/"

<div class="m-2">
<EditForm Model="@parameter" OnValidSubmit="@Submit">
<div class="bg-info p-2">
    Some edit fields
</div> 
<div class="p-2">
    <button class="btn btn-primary" type="submit">Submit</button>
</div> 
</EditForm>
</div>

@if (isLoading)
{
    <div class="spinner"><h3 class="text-danger">Spinning....</h3></div>
}
else if(emptyResult)
{
    <div>
        <span class="text-danger">
            No data for given parameters.
        </span>
    </div>
}
else if (data != null)
{
    <div>
        <span class="text-white bg-dark p-2">
            Data : @data.Value
        </span>
    </div>
}

else
{
    <div>
        <span class="text-white bg-danger p-2">
            No Data to Display
        </span>
    </div>
}

@code{
    private MyData parameter = new MyData();
    private MyData? data;
    private bool toggle;

    private bool isLoading = false;
    private bool emptyResult = false;

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
    }

    private async Task Submit()
    {
        emptyResult = false;
        isLoading = true;
        await LoadDataAsync();
        isLoading = false;
        toggle = !toggle;
    }

    private async Task LoadDataAsync() 
    {
        //  emulate an async call
        await Task.Delay(1000);
        data = toggle
            ? data = null
            : data = new MyData {Value = $"updated at {DateTime.Now.ToLongTimeString()}"};

        if(data is null)
            emptyResult = true;
        else 
            emptyResult = false;
    }

    public class MyData
    {
        public string Value { get; set; } = string.Empty;
    }

 }

The symptoms indicate that await service.GetData(parameter) is not async (enough). Ensure your action releases the Thread, do that in the top UI method:

private async Task Submit()
{
    emptyResult = false;
    isLoading = true;
    await Task.Delay(1);    // add this
    await LoadDataAsync();
    isLoading = false;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM