Home > database >  Blazor Appstate doesn't update ChildComponent
Blazor Appstate doesn't update ChildComponent

Time:11-20

Trying to pass down variabels with an AppState class, the components updates when the call happends in the same component but not in a childcomponent when the parrent triggers the event.

Parent

@code {
    [Parameter]
    public int Id { get; set; }

    WikiDetailDto wikiDetail = null;

    protected async override Task OnInitializedAsync()
    {
        Console.WriteLine("going in detail INIT");
        AppState.OnCurrentWikiPageChanged  = StateHasChanged;
        AppState.SetCurrentWikiPage(await wikiPageService.GetDetail(Id));
        wikiDetail = AppState.CurrentWikiPage;

        Console.WriteLine("Retrieved WikiDetail!");
    }
}

Child

<MudDrawer Anchor="Anchor.End" Open="true">
    <MudDrawerHeader>Recommendations</MudDrawerHeader>
    @if(AppState.CurrentWikiPage != null)
    {
        @(RecommendedWikiPages = CalculateReccomendedWikis(AppState.CurrentWikiPage));
        if(RecommendedWikiPages != null)
        {
            foreach(var p in RecommendedWikiPages)
            {
                <MudCard>
                    <MudCardContent>
                        <MudText>@p.Name</MudText>

                    </MudCardContent>
                </MudCard>
            }
        }
    }
    else
    {
        <p>Loading...</p>
    }

When AppState.CurrentWikiPage gets updated, it doesn't check the if statement of the cild. What is best practice here? I don't want to use cascading values.

AppState

public WikiDetailDto CurrentWikiPage { get; set; }
        public event Action OnCurrentWikiPageChanged;
        public void SetCurrentWikiPage(WikiDetailDto wikiPage)
        {
            CurrentWikiPage = wikiPage;
            OnCurrentWikiPageChanged?.Invoke();
        }

CodePudding user response:

If I'm reading your code correctly, the child component needs to register for the OnCurrentWikiPageChanged event.

Your child needs to look like this:

@implements IDisposable
..... markup code


    protected async override Task OnInitializedAsync()
    {
        AppState.OnCurrentWikiPageChanged  = StateHasChanged;
    }

    public void Dispose()
    {
        AppState.OnCurrentWikiPageChanged -= StateHasChanged;
    }

Personally I would not link StateHasChanged directly to the event handler. Its bad practice because StateHasChanged has to run the the UI context thread. If the event caller is running on another thread, you'll get an exception. I would stick with a standard EventHandler. WASM may be single threaded now, but it may not be forever.

My Handler would look something like:

private void OnxxxChanged(object sender, EventArgs e)
      => this.InvokeAsync(StateHasChanged);
  • Related