WebAssembly performance in Blazor DataGrid
4 Dec 202512 minutes to read
This section outlines performance guidelines for using the Syncfusion Blazor DataGrid efficiently in Blazor WebAssembly applications. General Blazor WebAssembly performance guidance is available in the Microsoft documentation.
NOTE
Refer to Getting Started for configuration details: Blazor Server DataGrid and Blazor WebAssembly DataGrid using Visual Studio.
Avoid unnecessary component renders
During the Blazor diffing process, each DataGrid cell and child component is evaluated for re-rendering. Event callbacks can trigger additional renders across the component tree. Fine-grained control over DataGrid rendering helps avoid unnecessary work.
Use PreventRender on the DataGrid instance to skip participation in the next render cycle. This method internally affects the DataGrid’s ShouldRender behavior.
In the following example:
- PreventRender is called in a click callback.
- The DataGrid is excluded from the render cycle caused by the click, and only currentCount updates.
@using Syncfusion.Blazor.Grids
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
<SfGrid @ref="grid" DataSource="@Orders" AllowPaging="true">
<GridColumns>
<GridColumn Type="ColumnType.CheckBox" Width="50"></GridColumn>
<GridColumn Field=@nameof(OrderData.OrderID) HeaderText="Order ID" TextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field=@nameof(OrderData.CustomerID) HeaderText="Customer Name" Width="150"></GridColumn>
<GridColumn Field=@nameof(OrderData.OrderDate) HeaderText=" Order Date" Format="d" Type="ColumnType.Date" TextAlign="TextAlign.Right" Width="130"></GridColumn>
<GridColumn Field=@nameof(OrderData.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field="@nameof(OrderData.Verified)" DisplayAsCheckBox="true" Width="70"></GridColumn>
</GridColumns>
</SfGrid>
@code {
SfGrid<OrderData> grid { get; set; }
private int currentCount = 0;
public List<OrderData> Orders { get; set; }
protected override void OnInitialized()
{
Orders = OrderData.GetAllRecords();
}
private void IncrementCount()
{
grid.PreventRender();
currentCount++;
}
}public class OrderData
{
public static List<OrderData> Orders = new List<OrderData>();
public OrderData() { }
public OrderData(int orderID, string customerID, double freight, DateTime? orderDate)
{
this.OrderID = orderID;
this.CustomerID = customerID;
this.Freight = freight;
this.OrderDate = orderDate;
}
public static List<OrderData> GetAllRecords()
{
if (Orders.Count == 0)
{
Orders.Add(new OrderData(10248, "VINET", 32.38, new DateTime(1996, 7, 4)));
Orders.Add(new OrderData(10249, "TOMSP", 11.61, new DateTime(1996, 7, 5)));
Orders.Add(new OrderData(10250, "HANAR", 65.83, new DateTime(1996, 7, 6)));
Orders.Add(new OrderData(10251, "VINET", 41.34, new DateTime(1996, 7, 7)));
Orders.Add(new OrderData(10252, "SUPRD", 151.30, new DateTime(1996, 7, 8)));
Orders.Add(new OrderData(10253, "HANAR", 58.17, new DateTime(1996, 7, 9)));
Orders.Add(new OrderData(10254, "CHOPS", 22.98, new DateTime(1996, 7, 10)));
Orders.Add(new OrderData(10255, "VINET", 148.33, new DateTime(1996, 7, 11)));
Orders.Add(new OrderData(10256, "HANAR", 13.97, new DateTime(1996, 7, 12)));
}
return Orders;
}
public int OrderID { get; set; }
public string CustomerID { get; set; }
public double Freight { get; set; }
public DateTime? OrderDate { get; set; }
public bool Verified { get; set; }
}
PreventRenderaccepts a Boolean argument to disable (true) or enable (false) participation in rendering.- Call
PreventRenderonly after the DataGrid completes its initial render; calling during initial render has no effect.
Avoid unnecessary component renders after Blazor DataGrid events
When callback methods are assigned to DataGrid events, the parent component re-renders once the event completes. To prevent re-rendering of the DataGrid in that cycle, set the PreventRender property on the corresponding event args to true (when available).
In the following example:
-
RowSelected invokes a callback that would normally trigger
StateHasChangedin the parent. - Setting
RowSelectEventArgs<Order>.PreventRenderto true prevents the DataGrid from participating in that re-render.
@using Syncfusion.Blazor.Grids
<p>Selected OrderID: <span style="color:red">@SelectedOrder.OrderID</span></p>
<SfGrid @ref="grid" DataSource="@Orders">
<GridSelectionSettings PersistSelection="true"></GridSelectionSettings>
<GridColumns>
<GridColumn Type="ColumnType.CheckBox" Width="50"></GridColumn>
<GridColumn Field=@nameof(OrderData.OrderID) IsPrimaryKey="true" HeaderText="Order ID" TextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field=@nameof(OrderData.CustomerID) HeaderText="Customer Name" Width="150"></GridColumn>
<GridColumn Field=@nameof(OrderData.OrderDate) HeaderText=" Order Date" Format="d" Type="ColumnType.Date" TextAlign="TextAlign.Right" Width="130"></GridColumn>
<GridColumn Field=@nameof(OrderData.Freight) HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field="@nameof(OrderData.Verified)" DisplayAsCheckBox="true" Width="70"></GridColumn>
</GridColumns>
<GridEvents TValue="OrderData" RowSelected="OnRowSelected"></GridEvents>
</SfGrid>
@code {
SfGrid<OrderData> grid { get; set; }
OrderData SelectedOrder = new OrderData { };
public List<OrderData> Orders { get; set; }
protected override void OnInitialized()
{
Orders = OrderData.GetAllRecords();
}
private void OnRowSelected(RowSelectEventArgs<OrderData> args)
{
args.PreventRender = true; //Without this, you may see noticeable delay in selection with rows in Grid.
SelectedOrder = args.Data;
}
}public class OrderData
{
public static List<OrderData> Orders = new List<OrderData>();
public OrderData() { }
public OrderData(int orderID, string customerID, double freight, DateTime? orderDate)
{
this.OrderID = orderID;
this.CustomerID = customerID;
this.Freight = freight;
this.OrderDate = orderDate;
}
public static List<OrderData> GetAllRecords()
{
if (Orders.Count == 0)
{
Orders.Add(new OrderData(10248, "VINET", 32.38, new DateTime(1996, 7, 4)));
Orders.Add(new OrderData(10249, "TOMSP", 11.61, new DateTime(1996, 7, 5)));
Orders.Add(new OrderData(10250, "HANAR", 65.83, new DateTime(1996, 7, 6)));
Orders.Add(new OrderData(10251, "VINET", 41.34, new DateTime(1996, 7, 7)));
Orders.Add(new OrderData(10252, "SUPRD", 151.30, new DateTime(1996, 7, 8)));
Orders.Add(new OrderData(10253, "HANAR", 58.17, new DateTime(1996, 7, 9)));
Orders.Add(new OrderData(10254, "CHOPS", 22.98, new DateTime(1996, 7, 10)));
Orders.Add(new OrderData(10255, "VINET", 148.33, new DateTime(1996, 7, 11)));
Orders.Add(new OrderData(10256, "HANAR", 13.97, new DateTime(1996, 7, 12)));
}
return Orders;
}
public int OrderID { get; set; }
public string CustomerID { get; set; }
public double Freight { get; set; }
public DateTime? OrderDate { get; set; }
public bool Verified { get; set; }
}
args.PreventRenderaffects rendering only for the event-triggered cycle and does not change component state beyond that cycle.- Prefer setting
PreventRenderto true for user-interactive events (for example, RowSelected, RowSelecting) to reduce UI latency. For events without args (for example, DataBound), call the grid’sPreventRendermethod.
Use paging or virtualization to load only visible rows
The DataGrid renders each row and cell as a component. Rendering a large number of elements can impact memory and CPU. Load only what is visible using Paging or Virtualization. Keep page sizes reasonable to avoid reintroducing performance bottlenecks even with these features enabled.
NOTE
Even with paging or virtualization, very large page sizes can still cause performance issues. Choose sizes that balance usability and responsiveness.