Mohammed Alwedaei
Mohammed Alwedaei

Reputation: 741

StateHasChanged is not Rendering the component when even Action is invoked

I'm trying to trigger StateHasChanged when the button is clicked. This is done by adding StateHasChanged to event Action. When debugging I can see that the Invoke method of the event is being fired but the UI is not re-rendering.

This is the flow I want it work like:

  1. The button is clicked in OgToolbar.razor.cs
  2. The event is triggered
  3. StorageManagerService changes the state in the local storage and invokes the event
  4. The UI is re-rendering in OgSidebar.razor.cs

OgSidebar.razor.cs where the UI must re-render

protected override void OnInitialized()
{
     StorageManagerService.OnChange += StateHasChanged;
}

protected override async Task OnInitializedAsync()
{
    var containsKey = await StorageManagerService.ContainsKeyAsync("isSidebarToggled");

    if (containsKey == false)
        await StorageManagerService.SetItemAsync("isSidebarToggled", true);

    _isSidebarToggled = await StorageManagerService.GetItemByKeyAsync<bool> 
                        ("isSidebarToggled");
}

public void Dispose()
{
    StorageManagerService.OnChange -= StateHasChanged;
}

OgToolbar.razor.cs where the button is clicked and triggers the event

[Inject]
private IStorageManagerService StorageManagerService { get; set; }

private bool _isSidebarToggled = false;

protected override void OnInitialized()
{
    StorageManagerService.OnChange += StateHasChanged;
}

protected override async Task OnInitializedAsync()
{
    var containsKey = await StorageManagerService.ContainsKeyAsync("isSidebarToggled");

    if (containsKey == false)
        await StorageManagerService.SetItemAsync("isSidebarToggled", true);

    _isSidebarToggled = await StorageManagerService.GetItemByKeyAsync<bool>("isSidebarToggled");
}

public void Dispose()
{
    StorageManagerService.OnChange -= StateHasChanged;
}

StorageManagerService.cs where the state is managed in local storage using Blazored:

private readonly ILocalStorageService _localStorageService;

public event Action OnChange;

public async Task<T> GetItemByKeyAsync<T>(string identifier)
{
    var itemFromLocalStorage = await _localStorageService.GetItemAsync<T>(identifier);

    return itemFromLocalStorage;
}

public async Task<bool> ContainsKeyAsync(string identifier)
{
    return await _localStorageService.ContainKeyAsync(identifier);
}

public async Task SetItemAsync<T>(string identifier,T item)
{
    await _localStorageService.SetItemAsync(identifier, item);

    OnChange.Invoke();
}

Upvotes: 1

Views: 745

Answers (1)

Henk Holterman
Henk Holterman

Reputation: 273179

You trigger the event but the state of _isSidebarToggled is not refreshed.

Roughly:

//OgSidebar.razor.cs

protected override void OnInitialized()
{
     StorageManagerService.OnChange += async () => 
       { 
         _isSidebarToggled = await StorageManagerService
            .GetItemByKeyAsync<bool> ("isSidebarToggled");
          StateHasChanged ();
       };
}

Using async void for the eventhandler is a little iffy.

Upvotes: 2

Related Questions