Search code examples
blazorblazor-webassembly

Blazor component lifecycle method OnParametersSet behavior


I'm learning Blazor and trying to figure out how components lifecycle methods works.

In my WASM project, I've created a simple component:

public class TestComponent : ComponentBase
{
    [Parameter]
    public string Id { get; set; }

    [Parameter]
    public RenderFragment ChildContent { get; set; }

    protected override void OnParametersSet()
    {
        base.OnParametersSet();

        Console.WriteLine($"({Id}) {nameof(OnParametersSet)}()");
    }

    protected override void BuildRenderTree(RenderTreeBuilder builder)
    {
        base.BuildRenderTree(builder);

        Console.WriteLine($"({Id}) {nameof(BuildRenderTree)}()");
        builder.AddContent(0, this.ChildContent);
    }
}

And added 2 instances of this component on the page:

<TestComponent Id="TestComponent1">
    <input class="input" type="text" value="" />
</TestComponent>

<TestComponent Id="TestComponent2">
    <input class="input" type="text" value="" @onchange="() => { }" />
</TestComponent>

Now, I see this log in a browser console when page loads:

blazor.webassembly.js:1 (TestComponent1) OnParametersSet()
blazor.webassembly.js:1 (TestComponent2) OnParametersSet()
blazor.webassembly.js:1 (TestComponent1) BuildRenderTree()
blazor.webassembly.js:1 (TestComponent2) BuildRenderTree()

That is expected as the components are just created. If I update TestComponent1 value, nothing happens.

But if I update TestComponent2 value I see the same log. I guess that is because TestComponent2 have attached event handler, that causes component update every time. I'm stuck with the following questions:

  • Why updating TestComponent2 value triggers lifecycle methods for TestComponent1? How they are related?

  • Why OnParametersSet is fired? According to official documentation, this method should be called:

after component is initialized or when the parent component re-renders

None of these are my case, IMO.


Solution

  • But if I update TestComponent2 value I see the same log.
    

    When you update the TestComponent2's value a UI event is triggered and the StateHasChanged method is called to notify the component that his state has changed and that it should re-render. When the parent component re-render, both child components re-render: or when the parent component re-renders

    You may test in the parent component( OnAfterRender method) that each time you update the TestComponent2's value, the parent component re-render.

    Note: If you place a "DoNothing" button in the parent component instead of @onchange="() => { }", the same behavior is expected.

    All this is related to the use of RenderFragment delegate property ChildContent, without which this re-rendering of both child components won't occur. That is to say, if you won't use child content in your component, the OnParametersSet will fire only for the child component whose state has changed.

    Here's a link to a github's issue for a similar question to yours...