Blazor Components Razor File

Published on Saturday, December 30, 2023

Components - Razor File

Prefer explicitly stating the inheritance of the component in the markup if the component does not derive from ComponentBase, and not in the _imports.razor file.

Prefer code in code-behind, not markup.

Don’t: 🙁

<img src="@(!mention.ProfilePictureUrl.IsNullOrEmpty()
  ? mention.ProfilePictureUrl
  : DefaultConstants.AvatarUrl)" />

Do: 🙂

Razor file:

<img src="@ProfileUrl" />

Code file:

private string ProfileUrl => !Mention.ProfilePictureUrl.IsNullOrEmpty()
  ? Mention.ProfilePictureUrl
  : DefaultConstants.AvatarUrl);

This is OK for simple code as above, but keep in mind that these properties get read very frequently, so you might want to precompute a complex value and store it in a field, rather than calculate it every time the property is read.

protected void OnParametersSet()
{
  base.OnParametersSet();
  if (SomeParameter != _oldSomeParameter)
  {
    _computedValue = ExpensiveCalculation(SomeParameter);
    _oldSomeParameter = SomeParameter;
}

This simple and manual caching mechanism would be tedious to extend to several properties, and a purpose-build caching class would be more appropriate at scale.

When looking at the markup of a page in the running app, it can be difficult to determine what component is having an issue. Add a “data-component-name” attribute to the outer element of a component (or add one, if it doesn’t have just one outer element) with the name of the component.

<div data-component-name="SomeComponent">
  @* Other markup here *@
 </div>

Only one @ per binding is necessary (and sometimes none is required, but...)

Blazor component tags can be self-closing if they have no contents, so consider:

<SomeBlazorComponent SomeParam=@_value />
@* Instead of... *@
 <SomeBlazorComponent SomeParam=@_value></SomeBlazorComponent>

Simplifying Callbacks

Don’t: 🙁

OnItemSelected="() => OnItemSelected()"

...or...

OnItemSelected="(e) => OnItemSelected(e)"

In either case, you can simplify it to:

OnItemSelected="@OnItemSelected"

When the handler (OnClick in this case) is an EventCallback, OnButtonClicked can be either sync or async:

OnClick="@OnButtonClicked"

If you want to pass an argument to either a sync or async method:

OnClick="() => OnButtonClicked(argument)"

This is an anti-pattern for EventCallbacks, so don’t do this:

Don’t: 🙁

OnClick="async () => await OnButtonClicked()" // Not necessary

UNLESS the handler is an Action:

OnSomeAction="async () => await OnButtonClicked() // Only this case

As a styling convention, private event handler methods don't need to be named "OnDoSomethingAsync", even if they are async.