ComponentBaseWithState

Base class providing state management helpers that reduce boilerplate and prevent redundant renders. ComponentBaseWithState extends FodComponentBase with automatic equality checking and thread-safe state updates.

Overview

ComponentBaseWithState provides state management helpers that automatically handle equality checking and state updates, significantly reducing boilerplate code.

Key Features

  • 83% less boilerplate code compared to manual state management
  • Automatic equality checking prevents redundant renders
  • Thread-safe state updates via InvokeAsync
  • Optional callbacks for derived state updates
  • Both synchronous and asynchronous variants
csharp
// Inherit from ComponentBaseWithState
public class MyComponent : ComponentBaseWithState
{
    private int _count;

    public int Count
    {
        get => _count;
        set => SetState(ref _count, value);
    }
}

SetState Method

Use SetState to update component state with automatic equality checking. The component only re-renders when the value actually changes.

Basic Counter

Count: 0
csharp
public class BasicStateDemo : ComponentBaseWithState
{
    private int _count;

    public int Count
    {
        get => _count;
        set => SetState(ref _count, value);
    }

    private void Increment() => Count++;
    private void Decrement() => Count--;
    private void Reset() => Count = 0;
}

SetState with Callbacks

Use the onChanged parameter to update derived state when a property changes. The callback is only invoked when the value actually changes.

Derived State Example

Full Name: (empty)
The full name is automatically updated via callback when first or last name changes.
csharp
private string _firstName = string.Empty;
private string _lastName = string.Empty;
private string _fullName = string.Empty;

public string FirstName
{
    get => _firstName;
    set => SetState(ref _firstName, value, UpdateFullName);
}

public string LastName
{
    get => _lastName;
    set => SetState(ref _lastName, value, UpdateFullName);
}

private void UpdateFullName()
{
    _fullName = $"{_firstName} {_lastName}".Trim();
}

Async Operations

Use SetStateAsync for async state updates with callback support. Perfect for scenarios where state changes need to trigger async operations.

Async Data Loading

Data: (no data)
Status: Ready
csharp
private async Task LoadDataAsync()
{
    var newData = await FetchDataAsync();

    var (changed, value) = await SetStateAsync(
        _data,
        newData,
        async () => await LogChangeAsync("Data updated")
    );

    if (changed)
    {
        _data = value;
    }
}

Equality Checking

SetState automatically compares old and new values. If they are equal, no render occurs and the callback is not invoked.

Redundant Render Prevention

Current Value
1
Set Attempts
0
Actual Changes
0

Try it: Click the same button multiple times. Notice that "Set Attempts" increases but "Actual Changes" only increases when the value truly changes. This demonstrates automatic equality checking preventing redundant renders.

csharp
public int Value
{
    get => _value;
    set
    {
        _setAttempts++;
        // SetState returns true only when value changed
        SetState(ref _value, value, OnValueChanged);
    }
}

private void OnValueChanged()
{
    // Only called when value actually changes
    _actualChanges++;
}

Performance Comparison

Compare the code required for manual state management vs. using SetState.

Without SetState (12 lines)

csharp
private int _count;

public int Count
{
    get => _count;
    set
    {
        if (EqualityComparer<int>
            .Default.Equals(_count, value))
        {
            return;
        }

        _count = value;
        UpdateDerivedState();
        InvokeAsync(StateHasChanged);
    }
}

With SetState (2 lines)

csharp
private int _count;

public int Count
{
    get => _count;
    set => SetState(
        ref _count,
        value,
        UpdateDerivedState);
}

// 83% reduction in boilerplate!

Type Support

SetState<T> is generic and works with primitives, enums, nullables, records, and structs.

Various Type Examples

String
Current:
Enum (Priority)
Nullable Int
Current: null
Record Type (Coordinates)
Current: (0, 0)
csharp
// String
public string StringValue
{
    get => _stringValue;
    set => SetState(ref _stringValue, value);
}

// Enum
public Priority EnumValue
{
    get => _enumValue;
    set => SetState(ref _enumValue, value);
}

// Nullable
public int? NullableValue
{
    get => _nullableValue;
    set => SetState(ref _nullableValue, value);
}

// Record (uses value equality)
public Coordinates RecordValue
{
    get => _recordValue;
    set => SetState(ref _recordValue, value);
}

Best Practices

Guidelines for effectively using ComponentBaseWithState in your components.

  • Always use SetState for property setters that need to trigger re-renders
  • Use callbacks for updating derived state instead of overriding properties
  • Choose SetStateAsync when callbacks need to perform async operations
  • Leverage equality checking by setting the same value without concern for redundant renders
  • Inherit from ComponentBaseWithState when building stateful FOD components
csharp
// Recommended pattern for FOD components
public class MyFodComponent : ComponentBaseWithState
{
    private string _value = string.Empty;
    private string _derivedValue = string.Empty;

    [Parameter]
    public string Value
    {
        get => _value;
        set => SetState(ref _value, value, OnValueChanged);
    }

    private void OnValueChanged()
    {
        // Update derived state when value changes
        _derivedValue = ComputeDerivedValue(_value);
    }
}

API Reference

ComponentBaseWithState protected methods and their descriptions.

No properties defined.

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please reload the page.