Move Blazor ShouldRender section (#22475)
parent
ef2ebc7614
commit
9e7edf2475
|
@ -40,7 +40,7 @@ The `Render` lifecycle:
|
|||
|
||||
1. Avoid further rendering operations on the component:
|
||||
* After the first render.
|
||||
* When [`ShouldRender`](#suppress-ui-refreshing-shouldrender) is `false`.
|
||||
* When [`ShouldRender`](xref:blazor/components/rendering#suppress-ui-refreshing-shouldrender) is `false`.
|
||||
1. Build the render tree diff (difference) and render the component.
|
||||
1. Await the DOM to update.
|
||||
1. Call [`OnAfterRender{Async}`](#after-component-render-onafterrenderasync).
|
||||
|
@ -207,28 +207,6 @@ Even if you return a <xref:System.Threading.Tasks.Task> from <xref:Microsoft.Asp
|
|||
|
||||
If event handlers are provided in developer code, unhook them on disposal. For more information, see the [Component disposal with `IDisposable`](#component-disposal-with-idisposable) section.
|
||||
|
||||
## Suppress UI refreshing (`ShouldRender`)
|
||||
|
||||
<xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> is called each time a component is rendered. Override <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> to manage UI refreshing. If the implementation returns `true`, the UI is refreshed.
|
||||
|
||||
Even if <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> is overridden, the component is always initially rendered.
|
||||
|
||||
`Pages/ControlRender.razor`:
|
||||
|
||||
::: moniker range=">= aspnetcore-5.0"
|
||||
|
||||
[!code-razor[](~/blazor/common/samples/5.x/BlazorSample_WebAssembly/Pages/lifecycle/ControlRender.razor)]
|
||||
|
||||
::: moniker-end
|
||||
|
||||
::: moniker range="< aspnetcore-5.0"
|
||||
|
||||
[!code-razor[](~/blazor/common/samples/3.x/BlazorSample_WebAssembly/Pages/lifecycle/ControlRender.razor)]
|
||||
|
||||
::: moniker-end
|
||||
|
||||
For more information on performance best practices pertaining to <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A>, see <xref:blazor/webassembly-performance-best-practices#avoid-unnecessary-rendering-of-component-subtrees>.
|
||||
|
||||
## State changes (`StateHasChanged`)
|
||||
|
||||
<xref:Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged%2A> notifies the component that its state has changed. When applicable, calling <xref:Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged%2A> causes the component to be rerendered.
|
||||
|
|
|
@ -25,9 +25,7 @@ By default, Razor components inherit from the <xref:Microsoft.AspNetCore.Compone
|
|||
Components inherited from <xref:Microsoft.AspNetCore.Components.ComponentBase> skip rerenders due to parameter updates if either of the following are true:
|
||||
|
||||
* All of the parameter values are of known immutable primitive types, such as `int`, `string`, `DateTime`, and haven't changed since the previous set of parameters were set.
|
||||
* The component's <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> method returns `false`.
|
||||
|
||||
For more information on <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A>, see <xref:blazor/webassembly-performance-best-practices#use-of-shouldrender>.
|
||||
* The component's [`ShouldRender` method](#suppress-ui-refreshing-shouldrender) returns `false`.
|
||||
|
||||
## Control the rendering flow
|
||||
|
||||
|
@ -35,6 +33,28 @@ In most cases, <xref:Microsoft.AspNetCore.Components.ComponentBase> conventions
|
|||
|
||||
For more information on the performance implications of the framework's conventions and how to optimize an app's component hierarchy for rendering, see <xref:blazor/webassembly-performance-best-practices#optimize-rendering-speed>.
|
||||
|
||||
## Suppress UI refreshing (`ShouldRender`)
|
||||
|
||||
<xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> is called each time a component is rendered. Override <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> to manage UI refreshing. If the implementation returns `true`, the UI is refreshed.
|
||||
|
||||
Even if <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> is overridden, the component is always initially rendered.
|
||||
|
||||
`Pages/ControlRender.razor`:
|
||||
|
||||
::: moniker range=">= aspnetcore-5.0"
|
||||
|
||||
[!code-razor[](~/blazor/common/samples/5.x/BlazorSample_WebAssembly/Pages/rendering/ControlRender.razor)]
|
||||
|
||||
::: moniker-end
|
||||
|
||||
::: moniker range="< aspnetcore-5.0"
|
||||
|
||||
[!code-razor[](~/blazor/common/samples/3.x/BlazorSample_WebAssembly/Pages/rendering/ControlRender.razor)]
|
||||
|
||||
::: moniker-end
|
||||
|
||||
For more information on performance best practices pertaining to <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A>, see <xref:blazor/webassembly-performance-best-practices#avoid-unnecessary-rendering-of-component-subtrees>.
|
||||
|
||||
## When to call `StateHasChanged`
|
||||
|
||||
Calling <xref:Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged%2A> allows you to trigger a render at any time. However, be careful not to call <xref:Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged%2A> unnecessarily, which is a common mistake that imposes unnecessary rendering costs.
|
||||
|
|
|
@ -33,57 +33,41 @@ The last two steps of this sequence continue recursively down the component hier
|
|||
If you want to interrupt this process and prevent rendering recursion into a particular subtree, then you can either:
|
||||
|
||||
* Ensure that all parameters to a certain component are of primitive immutable types (for example, `string`, `int`, `bool`, `DateTime`, and others). The built-in logic for detecting changes automatically skips rerendering if none of these parameter values have changed. If you render a child component with `<Customer CustomerId="@item.CustomerId" />`, where `CustomerId` is an `int` value, then it isn't rerendered except when `item.CustomerId` changes.
|
||||
* If you need to accept nonprimitive parameter values, such as custom model types, event callbacks, or <xref:Microsoft.AspNetCore.Components.RenderFragment> values, then you can override <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> to control the decision about whether to render, which is described in the [Use of `ShouldRender`](#use-of-shouldrender) section.
|
||||
* If you need to accept nonprimitive parameter values, such as custom model types, event callbacks, or <xref:Microsoft.AspNetCore.Components.RenderFragment> values or if authoring a UI-only component that doesn't change after the initial render (regardless of any parameter values), override <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> to control the decision about whether to render. The following example uses private fields to track the necessary information to detect changes. The value of `shouldRender` is based on checking for any kind of change or mutation that should prompt a rerender. `prevOutboundFlightId` and `prevInboundFlightId` track information for the next potential update:
|
||||
|
||||
```razor
|
||||
@code {
|
||||
[Parameter]
|
||||
public FlightInfo OutboundFlight { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public FlightInfo InboundFlight { get; set; }
|
||||
|
||||
private int prevOutboundFlightId;
|
||||
private int prevInboundFlightId;
|
||||
private bool shouldRender;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
shouldRender = OutboundFlight.FlightId != prevOutboundFlightId
|
||||
|| InboundFlight.FlightId != prevInboundFlightId;
|
||||
|
||||
prevOutboundFlightId = OutboundFlight.FlightId;
|
||||
prevInboundFlightId = InboundFlight.FlightId;
|
||||
}
|
||||
|
||||
protected override bool ShouldRender() => shouldRender;
|
||||
}
|
||||
```
|
||||
|
||||
In the preceding example, an event handler may also set `shouldRender` to `true` so that the component is rerendered after the event. For most components, this level of manual control isn't necessary. You should only be concerned about skipping rendering subtrees if those subtrees are particularly expensive to render and are causing UI lag. For more information, see <xref:blazor/components/lifecycle>.
|
||||
|
||||
For general information on `ShouldRender`, see <xref:blazor/components/rendering#suppress-ui-refreshing-shouldrender>.
|
||||
|
||||
By skipping rerendering of whole subtrees, you may be able to remove the vast majority of the rendering cost when an event occurs.
|
||||
|
||||
You may wish to factor out child components specifically so that you can skip rerendering that part of the UI. This is a valid way to reduce the rendering cost of a parent component.
|
||||
|
||||
#### Use of `ShouldRender`
|
||||
|
||||
If authoring a UI-only component that never changes after the initial render (regardless of any parameter values), configure <xref:Microsoft.AspNetCore.Components.ComponentBase.ShouldRender%2A> to return `false`:
|
||||
|
||||
```razor
|
||||
@code {
|
||||
protected override bool ShouldRender() => false;
|
||||
}
|
||||
```
|
||||
|
||||
If the component only requires rerendering when its parameter values mutate in particular ways, then you can use private fields to track the necessary information to detect changes. In the following example, `shouldRender` is based on checking for any kind of change or mutation that should prompt a rerender. `prevOutboundFlightId` and `prevInboundFlightId` track information for the next potential update:
|
||||
|
||||
```razor
|
||||
@code {
|
||||
[Parameter]
|
||||
public FlightInfo OutboundFlight { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public FlightInfo InboundFlight { get; set; }
|
||||
|
||||
private int prevOutboundFlightId;
|
||||
private int prevInboundFlightId;
|
||||
private bool shouldRender;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
shouldRender = OutboundFlight.FlightId != prevOutboundFlightId
|
||||
|| InboundFlight.FlightId != prevInboundFlightId;
|
||||
|
||||
prevOutboundFlightId = OutboundFlight.FlightId;
|
||||
prevInboundFlightId = InboundFlight.FlightId;
|
||||
}
|
||||
|
||||
protected override bool ShouldRender() => shouldRender;
|
||||
|
||||
// Note that
|
||||
}
|
||||
```
|
||||
|
||||
In the preceding code, an event handler may also set `shouldRender` to `true` so that the component is rerendered after the event.
|
||||
|
||||
For most components, this level of manual control isn't necessary. You should only be concerned about skipping rendering subtrees if those subtrees are particularly expensive to render and are causing UI lag.
|
||||
|
||||
For more information, see <xref:blazor/components/lifecycle>.
|
||||
|
||||
::: moniker range=">= aspnetcore-5.0"
|
||||
|
||||
### Virtualization
|
||||
|
|
Loading…
Reference in New Issue