전체 소스 코드는 다음 Github 의 AppStateService 폴더 에 있습니다. 미리 다운로드 해서 실행해 보시면 더 쉽게 이해할 수 있습니다.
blazor wasm 기본 Template 으로 프로젝트를 생성해 보면 다음과 같은 구조로 생성이 됩니다.

MainLayout 하위 트리에 NavMenu 와 Index 를 가지는 구조입니다.
로그인 상태를 표시하는 텍스트는 MainLayout 우측 상단 갱신영역으로 표시한 부분에 있습니다.
index 페이지에서 Toggle login status 버튼을 클릭하면 사이트 상단에 표시되는 로그인 상태 텍스트를 갱신하고자 합니다.
코드로 보면 index 페이지에 있는 버튼을 클릭하는 경우 index 페이지의 부모 트리에 존재하는 MainLayout component 에 존재하는 텍스트가 갱신이 되어야 합니다.
이를 위해 서비스(AppStateService) 를 하나 추가해서 구현해 보겠습니다.
로그인 상태를 저장하는 프로퍼티와 로그인 상태가 변경되었음을 알리기 위한 메서드 와 이를 수신하기 위한 이벤트를 가지는 서비스 클래스를 추가합니다.
public class AppStateService
{
public AppStateService()
{
}
public bool IsLogin { get; set; }
public async Task UpdateLoginStatus()
{
if (OnUpdateLoginStatus != null)
{
await OnUpdateLoginStatus.Invoke();
}
}
public event Func<Task>? OnUpdateLoginStatus;
}
Program.cs 에서 AppStateService 서비스를 등록합니다.
builder.Services.AddSingleton<AppStateService>();
버튼을 클릭해서 로그인 상태를 변경하고 통지하기 위해 index.razor 파일을 다음과 같이 수정합니다.
@page "/"
@using BlazorApp.Services
@inject AppStateService AppState
<PageTitle>AppStateService sample</PageTitle>
<button class="btn btn-primary" @onclick="ToggleLoginStatus">Toggle login status</button>
@code {
private async Task ToggleLoginStatus()
{
AppState.IsLogin = !AppState.IsLogin;
await AppState.UpdateLoginStatus();
}
}
사이트 상단에 로그인 상태를 표시하고 로그인 상태가 변경되면 로그인 상태를 갱신하기 위해 MainLayout.razor 파일을 다음과 같이 수정합니다.
@inherits LayoutComponentBase
@using BlazorApp.Services
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
Login status : @(AppState.IsLogin ? "Login" : "Not login")
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
@code {
[Inject]
AppStateService AppState { get; set; }
protected override async Task OnInitializedAsync()
{
AppState.OnUpdateLoginStatus += async () => { await InvokeAsync(StateHasChanged); };
await Task.CompletedTask;
}
}
앞서 설명하는 방법 외에도 CascadingValue 와 CascadingParameter 등 다양한 방법으로 구현이 가능하지만 좀 더 복잡하고 다양한 상황(부모<->자식, 페이지<->페이지 등)에서 비교적 간단하면서도 호환성이 좋은 방법이라 생각합니다.
0 Comments