Below is a link to a question answered by me and by Henk Holterman
, in whose answer he uses await Task.Delay(1);
Run the code, and see the difference, as for instance, using await Task.Delay(1);
results in re-rendering the component twice, etc.
Is the use of await Task.Delay(1);
necessary?
Absolutely not. This is a bad practice that not only results in a second re-rendering of a component, but it may lead to subtle issues with complex code. Blazor offers a list of life-cycle methods which you can capture and use to provide the wanted solutions. No hacking, please. This may prove very expensive in the long run. Create elegant code, not hacking...
UPDATE
The code snippet below describes a use case for the use of Task.Delay,
demonstrating a page with a button element with the caption "Save," The requirement is to alter the caption's text to "Saving...," immediately after the user clicks the button, for the duration of saving an employee record in a data store. If you know of other use cases for Task.Delay,
please let me know.
Index.razor
@page "/"
<div>
<button class="btn btn-primary"
@onclick="Save">@caption</button>
</div>
@code
{
private string caption = "Save";
private async Task SaveEmployee()
{
// Simulate saving an employee's record in database...
// I use System.Threading.Thread.Sleep instead of a loop
// with millions of iterations.
System.Threading.Thread.Sleep(3000);
// Retruns completed task
await Task.CompletedTask;
}
private async Task Save()
{
caption = "Saving...";
// Renders here automatically after calling Task.Delay()
await Task.Delay(1000);
await SaveEmployee();
caption = "Save";
// Renders here automatically when SaveEmployee()
//complete
}
}
On the other hand, the following code snipppet demonstrates how to not use Task.Delay,
and provides an elegant solution, which is certainly not an hack, and whose additional advantage is that it results in a single rendering of the component... Task.Delay
involve a second rendering, mind you...
Note: The code below is an answer to this question
Component.razor
<div @ref="ReferenceToDiv" id="select-@Id" style="background-color: red; width:300px; height: 300px">
</div>
@code
{
ElementReference ReferenceToDiv;
// As you can see, you should call the "adjustPosition" method from the
// `OnAfterRenderAsync` method to ensure that the div element has been
// rendered. DO Not Re-render In Vain. That is, do not use
// await Task.Delay(1); to re-render your component
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (opened)
{
await jsModule.InvokeVoidAsync("adjustPosition", ReferenceToDiv);
}
}
public void OnClick()
{
opened = !opened;
}
}
test.js
export function adjustPosition(element) {
// Should return 300px
console.log($(element.style.width);
}