Событие не инициируется, и компонент Blazor не обновляется - PullRequest
0 голосов
/ 06 января 2020

Я хочу сделать мой компонент refre sh на основании изменения авторизации. Вот мой компонент:

@inject IAuthService AuthService
@implements IDisposable

<AuthorizeView>
    <Authorized>
        Logged as: @Identity
    </Authorized>
    <NotAuthorized>
    </NotAuthorized>
</AuthorizeView>

@code
{
    private string Identity { get; set; }

    protected override async Task OnInitializedAsync()
    {
        AuthService.RefreshRequested += StateHasChanged;
        Identity = $"{(await AuthService.GetClaimFromToken("sub"))?.Value} ({(await AuthService.GetClaimFromToken("unique_name"))?.Value})";
    }

    public void Dispose()
    {
        AuthService.RefreshRequested -= StateHasChanged;
    }
}

, а вот часть моего сервиса:

    public class AuthService: IAuthService
    {
        // ...
        public event Action RefreshRequested;

        public async Task<RequestResponse> Token(LoginModel loginModel)
        {
            // some logic

            CallRequestRefresh();

            return JsonConvert.DeserializeObject<RequestResponse>(result);
        }

        private void CallRequestRefresh()
        {
            RefreshRequested?.Invoke();
        }
    }

Token(...) метод используется в другом компоненте. Я не знаю, почему в упомянутом компоненте StateHasChanged не срабатывает.

Все, чего я на самом деле хочу достичь, - это предоставить какой-нибудь способ обновить свойство Identity, используя данный асинхронный метод (GetClaimFromToken).

1 Ответ

0 голосов
/ 07 января 2020

Мне наконец удалось решить мою проблему. Я не мог использовать свой сервис, потому что он не был зарегистрирован как Singleton. Я создал класс AppState и зарегистрировал его как Singleton:

    public class AppState
    {
        public event Action RefreshRequested;

        public void TriggerRefreshAction()
        {
            StateChanged();
        }

        private void StateChanged()
        {
            RefreshRequested?.Invoke();
            Console.WriteLine("State has changed");
        }
    }

и внедрил его в компонент и AuthService. Также мне нужно было изменить некоторые логики c моего компонента как StateHasChanged() триггеры OnAfterRender/OnAfterRenderAsync, которые обновляют мою строку Identity, но не изменяют пользовательский интерфейс. Кажется, сейчас работает, но мне не нравится подход обновления значения в пользовательском интерфейсе:

@inject IAuthService AuthService
@inject AppState AppState
@implements IDisposable

<AuthorizeView>
    <Authorized>
        Logged as: @Identity
    </Authorized>
    <NotAuthorized>
    </NotAuthorized>
</AuthorizeView>

@code
{
    private string Identity { get; set; }
    private bool Refresh { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        await UpdateIdentity();
        AppState.RefreshRequested += RefreshComponent;
    }

    public void Dispose()
      => AppState.RefreshRequested -= RefreshComponent;

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (Refresh)
        {
            await UpdateIdentity();
            Refresh = false;
            StateHasChanged();
        }
        await base.OnAfterRenderAsync(firstRender);
    }

    private async Task UpdateIdentity()
      => Identity = $"{(await AuthService.GetClaimFromToken("sub"))?.Value} ({(await AuthService.GetClaimFromToken("unique_name"))?.Value})";

    private void RefreshComponent()
    {
        Refresh = true;
        StateHasChanged();
    }
}

Должно быть лучшее решение.

...