Understanding Blazor Components

This Dev Note is a practical walkthrough of several core Blazor concepts: components, state, rendering, parameters, and communication between parent and child components.

Rather than trying to explain all of Blazor at once, this note focuses on the main patterns that make Blazor applications work. The goal is to make the framework easier to reason about, not just easier to copy from examples.

Main Focus

Components, state, rendering, communication

Framework

Blazor / Razor Components

Use Case

Learning the mental model behind Blazor UI development

What Makes Blazor Different?

Blazor lets developers build interactive web interfaces using C# and Razor components instead of relying entirely on JavaScript for client-side behavior. A Blazor component combines markup and logic in a single .razor file.

This means UI behavior can often be written using the same language and tooling used elsewhere in a .NET application.

A useful mental model is this: a Blazor component is a reusable UI unit with its own markup, state, and behavior.

A Simple Blazor Component

Here is a small component that displays a message and updates it when a button is clicked:

<h3>Hello Blazor</h3>

<p>@message</p>

<button @onclick="ChangeMessage">Click me</button>

@code {
    string message = "The component is alive.";

    void ChangeMessage()
    {
        message = "The message changed!";
    }
}

This example demonstrates several important ideas at once:

  • Markup and C# logic live in the same component
  • @message inserts C# state into the rendered output
  • @onclick binds a UI event to a C# method
  • Changing component state causes the UI to update

State and Re-Rendering

A core concept in Blazor is that components render based on their current state. When the state changes, Blazor re-renders the component and updates the UI.

In the previous example, the value of message changes when the button is clicked. Blazor detects the change and updates the output shown in the browser.

A simple way to think about Blazor is: state changes drive UI updates. You usually do not manually edit the DOM yourself.

Lifecycle Basics

Blazor components have lifecycle methods that run at different moments during initialization and rendering.

A common early example is OnInitialized():

@code {
    string message = "";

    protected override void OnInitialized()
    {
        message = "Component initialized.";
    }
}

Some useful lifecycle methods to know early on are:

  • OnInitialized — runs when the component is initialized
  • OnParametersSet — runs when parameters are received or updated
  • OnAfterRender — runs after rendering has completed

You do not need to memorize them all immediately, but it helps to know that Blazor components follow a defined lifecycle rather than rendering magically out of nowhere.

Parameters: Passing Data to a Child Component

A Blazor component can accept values from a parent using parameters. This is one of the main ways components become reusable.

Example child component:

<h4>Hello @Name</h4>

@code {
    [Parameter]
    public string Name { get; set; }
}

Example parent usage:

<ChildComponent Name="Joel" />

Here the parent passes a value into the child component. The child receives it through a property marked with [Parameter].

A helpful analogy is that component parameters work somewhat like function arguments for UI components.

Sending Information Back Up with EventCallback

Passing data down is only part of component communication. Sometimes a child component needs to notify its parent that something happened.

Example child component:

<button @onclick="SendMessage">Notify Parent</button>

@code {
    [Parameter]
    public EventCallback<string> OnMessage { get; set; }

    async Task SendMessage()
    {
        await OnMessage.InvokeAsync("Child says hello.");
    }
}

Example parent usage:

<ChildComponent OnMessage="HandleMessage" />

@code {
    string childMessage = "";

    void HandleMessage(string message)
    {
        childMessage = message;
    }
}

This pattern allows a child component to trigger behavior in its parent without tightly coupling the two components together.

Blazor Server vs Blazor WebAssembly

Blazor has more than one hosting model, and understanding the distinction helps explain why different Blazor apps behave differently.

Blazor Server

  • Components execute on the server
  • The browser communicates with the server over SignalR
  • UI updates are sent back to the client

Blazor WebAssembly

  • The .NET runtime runs in the browser via WebAssembly
  • Components execute on the client
  • The app can behave more like a client-side SPA
These two models share a component style, but their execution environments are different. That affects performance, hosting, connectivity, and architecture.

A Tiny Mental Model

A concise way to think about many Blazor interactions is:

state → render → event → state

That loop appears again and again:

  • state is displayed in the UI
  • the UI renders based on that state
  • the user triggers an event
  • the event changes state
  • Blazor re-renders the component

A Simple Counter Example

This small example shows the state/render/event loop in one place:

<p>Count: @count</p>

<button @onclick="Increment">Increment</button>

@code {
    int count = 0;

    void Increment()
    {
        count++;
    }
}

Even though this example is tiny, the same pattern scales up into more complex interactive components and applications.

Why These Concepts Matter

It is easy to build Blazor pages by copying examples without forming a strong mental model. Understanding components, state, parameters, and callbacks makes the framework more predictable and easier to debug.

Once these ideas feel natural, larger topics such as forms, dependency injection, routing, and shared state become much easier to approach.

This page is intentionally foundational. A next Dev Note could build on this by walking through a small multi-component Blazor app or comparing Blazor patterns to React or MVC thinking.