I have a grid that when loading the data it is entering two times in ReadISHandler. I can see in debugger that enter and stops two times in LoadIS(); causing a performance problem, any idea what is happening
<TelerikGrid Data=@GridDataIS
TotalCount=@Total
Height=@Height
ScrollMode="@GridScrollMode.Virtual"
Sortable=false
RowHeight="40"
OnRead=@ReadISHandler>
protected async Task ReadISHandler(GridReadEventArgs args)
{
Skip = args.Request.Skip;
await LoadIS();
}
6 Answers, 1 is accepted
Hi Alberto,
Could you check if this is the situation that you hit: https://feedback.telerik.com/blazor/1442276-onread-called-twice-on-initialization? We are aware of such behavior during initialization and for the time being you can work around it through flags.
Regards,
Marin Bratanov
Progress Telerik
do you have any sample code on how to avoid this with flags?
Will this be fixed in next versions as i see the issue approved but not planned to any version.
Hello Alberto,
I posted one workaround in the public page: https://feedback.telerik.com/blazor/1442276-onread-called-twice-on-initialization
You can click the Follow button there to get notified about status changes. It will be fixed, because it is a valid issue, even if I cannot say in which release that will happen.
Regards,
Marin Bratanov
Progress Telerik
Hi Jason,
In a server-side Blazor app this behavior is expected - the pre-rendering actually initializes all components twice - once on the server for the pre-rendering, and once the client-side portion of the app spins up. This is the case with all components, not just the grid. For example, if you fetch data in the OnInitialized event, it will be called twice too. For example, if you make a GET for the FetchData page from the default template, and modify it as follow,s you will find that statement twice in the console:
protected override async Task OnInitializedAsync()
{
Console.WriteLine("fetching data");
forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
}
This behavior is expected and valid - for proper pre-rendering the components need to initialize and render, and for the grid that also means getting data.
If you want to reduce the calls, you must use some business logic to do that, for example, flag raised in the OnAfterRender event so you can call the OnRead handler yourself only then (a basic example of storing the grid request is available here: https://docs.telerik.com/blazor-ui/components/grid/manual-operations#cache-data-request). Here's another I made for you that uses a flag from OnAfterRender:
@using Telerik.DataSource
<TelerikGrid Data=@GridData TotalCount=@Total
Pageable=true PageSize=15
OnRead=@ReadItems>
<GridColumns>
<GridColumn Field=@nameof(Employee.Id) Title="ID" />
<GridColumn Field=@nameof(Employee.Name) Title="Name" />
</GridColumns>
</TelerikGrid>
@code {
public List<Employee> GridData { get; set; }
public int Total { get; set; } = 0;
bool hasComponentRenderedOnce { get; set; }
DataSourceRequest CurrentRequest { get; set; }
protected async Task ReadItems(GridReadEventArgs args)
{
CurrentRequest = args.Request;
if (hasComponentRenderedOnce)
{
await FetchData();
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
hasComponentRenderedOnce = true;
FetchData();
}
}
async Task FetchData()
{
if (CurrentRequest == null)
{
return;
}
Console.WriteLine("ReadItems"); // fetch actual data here and populate Total and GridData
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
}
Regards,
Marin Bratanov
Progress Telerik
Our thoughts here at Progress are with those affected by the outbreak.
protected override async Task OnInitializedAsync()
{
await LoadData();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await LoadData();
StateHasChanged();
}
That's the typical approach people tend to take in such cases.
I would only suggest you call
await InvokeAsync(StateHasChanged);
so that you are sure it executes in the main thread.