Search code examples
razorblazor

When to use @ref for child component in Blazor


The parent page has two child components and a button.
On page load, the two components should be visible.
The button click should toggle their visibility.

I'm able to achieve the desired output, but would like to understand the best way.

Index.razor

@page "/"    

<button @onclick="ToggleVisibility">Toggle Visibility</button>
<br />
<VisibilityComponent1 ShowComponent=visibilityState></VisibilityComponent1>
<br />
<VisibilityComponent2 @ref="visibilityComponent2"></VisibilityComponent2>

@code
{
    private bool visibilityState = true;
    private VisibilityComponent2 visibilityComponent2;

    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);
        visibilityComponent2.SetVisibility(visibilityState);
    }

    private void ToggleVisibility()
    {
        visibilityState = !visibilityState;
        visibilityComponent2.SetVisibility(visibilityState);
    }
}

VisibilityComponent1.razor

@if (ShowComponent)
{
    <h3>First Component</h3>
}

@code {
    [Parameter]
    public bool ShowComponent { get; set; }
}

VisibilityComponent2.razor

@if (showComponent)
{
    <h3>Second Component</h3>
}

@code {
    private bool showComponent;

    public void SetVisibility(bool isVisible)
    {
        showComponent = isVisible;
        StateHasChanged();
    }
}

For VisibilityComponent1, I have used the Parameter approach and for VisibilityComponent2, the @ref approach.

#1. I have used OnAfterRender to make VisibilityComponent2 visible. Is this the correct way?
#2. What is the difference between these two approaches. Could you please explain when to use which with any real-time example.


Solution

  • #2. What is the difference between these two approaches. Could you please explain when to use which with any real-time example.

    When you need to use the component as a variable you'd attach it to an @ref. Maybe pass it as a cascading value or call some method on it like visibilityComponent2.RefreshSomeData(). In your example you don't need to use the component as a variable. In doing so makes the code more complex for no reason. VisibilityComponent1 would be the way to go here.

    #1. I have used OnAfterRender to make VisibilityComponent2 visible. Is this the correct way?

    In your example you pretty much have to do it here because of the @ref. It will be null in OnInitialized and OnParametersSet. When your render mode is ServerPrerendered you'll generally want to put javascript and code that you only want to execute once in the OnAfterRender on the firstRender. If your render mode is Server you can get away with doing some things earlier in the life cycle (especially javascript). In Server mode each portion of the life cycle is only executed once.