Reputation: 27338
Consider child component with string parameter and with a complex type parameter.
<Child Name="@strProperty" />
<Child Model="@compelexType" />
Assuming neither parameter has changed, calling StateHasChanged on the parent component causes the Child component with complex parameter to rerender, but not with string parameter.
See this demo: https://blazorrepl.com/repl/wbYguGuA515uMYR742
How do you explain different behavior?
Upvotes: 1
Views: 1103
Reputation: 30016
This isn't an answer per se, I just need more space than in a comment.
I don't believe the quoted documentation fully explains the observed results.
The document states:
By default, Razor components inherit from the ComponentBase base class, which contains logic to trigger rerendering at the following times:
These are all internal actions. The first two occur after SetParametersAsync
has been called on the component. The last two from internal actions within the component.
Any child component activity, such as re-rendering, is triggered by the Renderer
calling SetParametersAsync
, not directly by the parent. The Renderer
makes this decision based on detected changes to any child component Parameter
's. So the reason the re-render occurs is because the Renderer
is deciding that it's an object and not primitive type, nothing to do with ComponentBase
.
To prove this I wrote a very basic component based on IComponent
rather than ComponentBase
. It looks like this:
using Blazor.Starter.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using System.Threading.Tasks;
namespace Blazor.Starter.Components.TestComponents
{
public class ObjectTest : IComponent
{
[Parameter] public DataModel Model { get; set; }
[Parameter] public int Value { get; set; }
private RenderHandle _renderHandle;
private int _renders;
public void Attach(RenderHandle renderHandle)
{
_renderHandle = renderHandle;
}
public Task SetParametersAsync(ParameterView parameters)
{
parameters.SetParameterProperties(this);
_renders++;
this.Render();
return Task.CompletedTask;
}
public void Render()
=> _renderHandle.Render(RenderComponent);
private void RenderComponent(RenderTreeBuilder builder)
{
builder.OpenElement(0, "div");
builder.AddContent(1, $"Rendered {_renders}");
builder.CloseElement();
}
}
}
If you set Model
in the parent SetParametersAsync
is called, if you only set Value
it doesn't. Same result.
Upvotes: 2
Reputation: 78155
Components inherited from
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
ShouldRender
method returnsfalse
.
Upvotes: 1
Reputation: 1107
As @GSerg said in a comment: It's because the primitive property didn't change, so it does not update.
Upvotes: 0