Search code examples
blazorblazor-component

Is there any reason to prefer communication via databinding over the use of @ref?


When I search for how to communicate from parent to child, almost all the material I find focuses on doing so through databinding. And when I first encountered the @ref directive, I got the impression that it was for use with JavaScript.

However, I now see that @ref is for more than that and it really simplified what I was trying to do so that I can call methods on a child component without having to add special data properties to my view model to do so.

The question I have is whether this is a perfectly normal, natural approach. Or might this be considered an anti-pattern in regard to some goals of Blazor. For example, if I wanted to write an application that would be hosted on other platforms via MAUI, might I run into any technical issues? Or might I be employing a bad design pattern that doesn't address problems which would be mitigated by communication via data-binding?

The @ref approach just seems so much simpler and straightforward, yet it was unexpectedly troublesome to figure this out based on my queries such as "communicating from parent to child component in Blazor".

To be clear, another way of asking my question would be: is @ref a "first class" citizen in Blazor. That is, I'm really not looking for subjective opinions on whether one approach is better or worse than another. I'm just trying to confirm that there are no obvious gotchas or pitfalls I might run into which may be considered common knowledge to any seasoned Blazor developer.

See my SO post and my answer to it here for a code example: Communicating with a list of components


Solution

  • To answer your initial question: Yes there are reasons. Components and the Renderer are designed to use binding.

    You probably haven't used Blazor long enough to be aware of the problems in trying to do everything directly through references to a component.

    1. You aren't in control of a component's lifecycle: the Renderer is. You can easily end up with a reference to an instance of a component that is not the current rendered one.

    2. You should not set any Parameters: treat them as read only. New values are applied to them when the the Renderer renders the component and calls SetParametersAsync.

    3. Any events or delegates that you set up to call back into the parent will not trigger a render of the parent: you will need to manage the parent rendering manually.

    If you choose to use @ref to replace binding, what seemed like a good idea at the time will probably come back to haunt you.