🦮 Blazor 입문
지난 시간에는 Form의 대해서 학습하는 시간을 가져보았다. Blazor에서 Form은 Modal을 통해서 header와 content를 나눠서 처리하였고, 값을 입력하는 부분에서 아무 내용을 넣지 않을 경우 그냥 저장되는 문제가 있어 Validation을 통해 이를 검증하고 확인하는 것까지 알아보았다. 이번 시간에는 State 관리 개념에 대해서 학습하는 시간을 가져보며, 마찬가지로 직접 실습하며 페이지를 제작해보도록 한다.
🏄♀️ State 관리
먼저 기존의 사용하던 BlazorApp, BlazorStudy 프로젝트를 삭제하고, 새롭게 BlazorApp 프로젝트를 하나 만들어 주도록하자. 이 후 프로그램을 실행하면, Counter 메뉴에서 Click Me를 클릭할 때마다 카운트가 증가하는 것을 볼 수 있다. 그러나 Count가 다른 메뉴를 클릭하면 값이 저장되지 않고 초기화되는 문제가 있는데, 오늘은 이를 일전에 알아본 서비스의 3가지 종류인 Singleton, Transient, Scoped를 중에 하나를 이용하여 초기화가 되지 않도록 관리해주도록 하자.
먼저 Data 폴더 밑으로 ConuterState 스크립트를 새롭게 만들어주고 변수를 get, set 처리해주자.
namespace BlazorApp.Data
{
public class CounterState
{
public int Count { get; set; }
}
}
이 후, 이를 사용하기 위해 Program.cs를 통해 Counter 서비스를 추가하도록 하자.
using BlazorApp.Data;
...
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
// Counter 서비스 추가
builder.Services.AddScoped<CounterState>();
...
app.Run();
이 후, Count 컴포넌트로 돌아가 의존성 주입을 처리하고 아래와 같이 스크립트를 작성 후 실행하도록 하자.
@page "/counter"
@* 의존성 주입 *@
@inject BlazorApp.Data.CounterState CounterState
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @CounterState.Count</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private void IncrementCount()
{
CounterState.Count = CounterState.Count + 1;
}
}
이 후, 프로그램을 실행하면 Counter의 값이 초기화 되지 않고, 계속해서 저장되고 있는 것을 볼 수 있다.
그러나 사실 이 또한 완벽하게 동작하지 않는데 바로 UI가 실시간으로 갱신되지 않는 기존의 문제가 발생한다. 따라서 이를 해결하도록 하자.
먼저 정상적으로 UI가 갱신되지 않는 문제점을 확인하기 위해 NavMenu 컴포넌트로 돌아가 UI를 설정해주도록 하자.
@* 의존성 주입 *@
@inject BlazorApp.Data.CounterState CounterState
...
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
<nav class="flex-column">
...
<div class="nav-item px-3">
<NavLink class="nav-link" href="fetchdata">
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
</NavLink>
</div>
</nav>
</div>
@* 갱신이 정상적으로 되지 않는 문제 발생 *@
<div>
<p style="color:white">Counter : @CounterState.Count</p>
</div>
@code {
private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
}
<div>를 통해 영역을 나누어지고 style을 통해 white를 선택한 후 Counter를 뿌려주는 UI를 생성해주도록 하자. 이 후 다른 메뉴에서 Counter의 값을 늘려줄 경우 값을 늘렸음에도 불구하고 NavMenu에 새롭게 생성한 Counter의 값이 정상적으로 바뀌지 않는 것을 볼 수 있다.
사실 이 문제는 일전에 해결한 적이 있는데, 이번에 다시한번 실습해보도록 한다. CounterState를 다음과 같이 바꿔주도록 하자.
namespace BlazorApp.Data
{
public class CounterState
{
public int _count = 0;
public Action OnStateChanged;
public int Count
{
get => _count;
set
{
_count = value;
Refresh();
}
}
void Refresh() => OnStateChanged?.Invoke();
}
}
먼저 get은 _count의 값을 반환하도록 설정하고, set의 경우 Refresh 함수를 통해 OnStateChanged 함수를 실행하도록 설정하자. 이 후 수정한 CounterState에 따라 NavMenu를 아래와 같이 수정해주도록 한다.
@* 의존성 주입 *@
@inject BlazorApp.Data.CounterState CounterState
@* IDisposable 인터페이스 구현 *@
@implements IDisposable
...
@* 갱신이 정상적으로 되지 않는 문제 발생 *@
<div>
<p style="color:white">Counter : @CounterState.Count</p>
</div>
@code {
private bool collapseNavMenu = true;
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null;
private void ToggleNavMenu()
{
collapseNavMenu = !collapseNavMenu;
}
protected override void OnInitialized()
{
// 구독 신청
CounterState.OnStateChanged += onStateChanged;
}
void onStateChanged()
{
this.StateHasChanged();
}
void IDisposable.Dispose()
{
// 구독 해제
CounterState.OnStateChanged -= onStateChanged;
}
}
먼저 OnInitialized 함수를 통해 프로그램이 실행될경우 onStateChanged 함수를 CounterState의 OnStageChaned에 추가(구독) 해주도록 하자. 이 후 IDisposable 인터페이스를 설정하여 IDisposable.Dispose 함수 내부에서 프로그램이 종료될 때 해제 (구독 해제)를 설정하면 끝이다.
이 후 프로그램을 실행할 경우 NavMenu의 다른 탭에서 Counter를 추가해주어도 정상적으로 NavMenu에 새롭게 추가한 Counter의 값이 정상적으로 바뀌는 것을 볼 수 있다.
'공부 > 인프런 - Rookiss' 카테고리의 다른 글
Part 6-6-1. Blazor 미니 프로젝트 : Blazor RankingApp #1 (2) | 2024.09.30 |
---|---|
Part 6-5-11. Blazor 입문 : Javascript 연동 (3) | 2024.09.20 |
Part 6-5-9. Blazor 입문 : Form, Validation (0) | 2024.09.15 |
Part 6-5-8. Blazor 입문 : SPA 구조, Router (0) | 2024.09.09 |
Part 6-5-7. Blazor 입문 : Dependency Injection, Service의 종류 (3) | 2024.09.09 |