Laurence Frost
Laurence Frost

Reputation: 2993

Blazor - subscribing to a property value change

When working with components in Blazor, I often need the child component to react to a parameter changing value, and do something accordingly.

In a simple example, I have a UserId parameter linked between the parent and child components. The idea is that when the parent changes the UserId value, the property setter in the child invokes a method which reads the required data. Here is some code to illustrate.

MyParent:

<ChildComponent UserId="@UserId" />

<a onclick="@ChangeUser">Load User</a>

@code
{
   public int UserId = 0;
   
   void ChangeUser()
   {
      UserId = 1;
   }
}

ChildComponent:

@if(userDetails != null)
{
   <div>First Name: @userDetails.FirstName</div>
   <div>Surname: @userDetails.Surname</div>
}


@code
{
   private int _userId;
   
   [Parameter] public int UserId
   {
      get => _userId;
      set
      {
         _userId = value;
         LoadUserDetails();
      }
   }
   UserDetails userDetails;
   
   async Task LoadUserDetails()
   {
      userDetails = [read from server here];
      StateHasChanged();
   }
}

Now whilst this works, what I don't like very much is that the property setter in ChildComponent is synchronous, yet it is calling asynchronous code (LoadUserDetails).

What is the cleanest way of updating the UserId in the parent, and having the child realise this and calling an async method in response without blocking any threads?

Upvotes: 1

Views: 1210

Answers (1)

agua from mars
agua from mars

Reputation: 17404

@code
{
   private int _userId;
   private bool _userIdChanged;
   
   [Parameter] public int UserId
   {
      get => _userId;
      set
      {
         _userIdChanged = value != _userId;
         _userId = value;
      }
   }
   UserDetails userDetails;
   
   async Task LoadUserDetails()
   {
      userDetails = [read from server here];
      StateHasChanged();
   }

    protected override async Task OnParametersSetAsync()
    {
         await base.OnParametersSetAsync().ConfigureAwait(false);
         if (_userIdChanged)
         {
             await LoadUserDetails().ConfigureAwait(false);
         }
    }
}

Upvotes: 3

Related Questions