이 문서와 이 노드의 다른 문서에서는 앱을 사용하는 동안 및 서버 미리 렌더링하는 동안을 포함하여 브라우저 세션에서 사용자의 데이터(상태)를 유지 관리하는 일반적인 방법을 설명합니다.
앱 개발 중에 Blazor 일반적인 요구 사항은 구성 요소 간에 상태를 공유하는 것입니다.
- 부모에서 자식으로: 부모 구성 요소는 매개 변수를 사용하여 자식 구성 요소에 상태를 전달합니다.
- 자식-부모: 자식 구성 요소는 해당 상태에 대한 데이터 바인딩을 사용하도록 설정하거나 콜백을 통해 상태를 제공합니다.
- 상위에서 하위 항목으로: 상위는 연계 값을 사용하여 모든 하위 항목과 상태를 공유합니다.
- 앱 전체: 상태는 구성된 앱 상태 서비스를 사용하여 전체 앱에서 공유됩니다.
- 회로당: 범위가 지정된 앱 상태 서비스를 사용하여 특정 회로에 대해 상태가 공유됩니다.
지속형 상태는 페이지 새로 고침, 다시 시작 회로 및 미리 렌더링에서 유지되어야 할 수 있습니다. 상태는 종종 중앙 관리, 추적 및 테스트가 필요합니다. 상태를 유지하기 위한 위치와 기술은 매우 가변적입니다.
Blazor 는 포괄적이고 의견이 있는 상태 관리를 제공하지 않습니다. Flux, Redux 및 MobX와 Blazor같이 원활하게 작동하는 타사 상태 컨테이너 제품 및 서비스는 거의 모든 앱 요구 사항을 충족합니다.
이 문서의 나머지 부분에서는 모든 유형의 Blazor 앱에 대한 일반 상태 관리 전략에 대해 설명합니다.
URL을 사용한 상태 관리
탐색 상태를 나타내는 임시 데이터의 경우 데이터를 URL 일부로 모델링합니다. URL에 모델링된 사용자 상태의 예는 다음과 같습니다.
- 표시된 엔터티의 ID
- 페이징 그리드의 현재 페이지 번호
브라우저의 주소 표시줄 내용은 다음과 같은 경우에 유지됩니다.
- 사용자가 페이지를 수동으로 다시 로드하는 경우
- 서버 쪽 시나리오만: 웹 서버를 사용할 수 없게 되고 사용자가 다른 서버에 연결하기 위해 페이지를 다시 로드해야 하는 경우
지시문을 사용하여 URL 패턴을 @page 정의하는 방법에 대한 자세한 내용은 ASP.NET Core Blazor 라우팅을 참조하세요.
메모리 내 상태 컨테이너 서비스
중첩된 구성 요소는 일반적으로 에서 설명하는 것처럼 Blazor을 사용하여 데이터를 바인딩합니다. 중첩된 구성 요소와 중첩되지 않은 구성 요소는 등록된 메모리 내 상태 컨테이너를 사용하여 데이터에 대한 액세스를 공유할 수 있습니다. 사용자 지정 상태 컨테이너 클래스는 할당 가능한 Action을 사용하여 앱의 서로 다른 구성 요소에게 상태 변경을 알립니다. 다음 예제에서
- 구성 요소 쌍은 상태 컨테이너를 사용하여 속성을 추적합니다.
- 다음 예제의 한 구성 요소는 다른 구성 요소에 중첩되어 있지만 이 방법을 사용하기 위해 중첩이 필요하지는 않습니다.
중요합니다
이 섹션의 예제에서는 메모리 내 상태 컨테이너 서비스를 만들고, 서비스를 등록하고, 구성 요소에서 서비스를 사용하는 방법을 보여 줍니다. 이 예제는 추가 개발 없이는 데이터를 유지하지 않습니다. 데이터의 영구 스토리지의 경우 상태 컨테이너는 브라우저 메모리를 지울 때 유지되는 기본 스토리지 메커니즘을 채택해야 합니다. 이 작업은 localStorage/sessionStorage 또는 다른 기술로 수행할 수 있습니다.
StateContainer.cs:
public class StateContainer
{
private string? savedString;
public string Property
{
get => savedString ?? string.Empty;
set
{
savedString = value;
NotifyStateChanged();
}
}
public event Action? OnChange;
private void NotifyStateChanged() => OnChange?.Invoke();
}
클라이언트 쪽 앱(Program 파일):
builder.Services.AddSingleton<StateContainer>();
서버 쪽 앱(Program 파일, .NET 6 이상의 ASP.NET Core):
builder.Services.AddScoped<StateContainer>();
서버 쪽 앱(Startup.ConfigureServicesStartup.cs일반적으로 .NET 6 이하)
services.AddScoped<StateContainer>();
Shared/Nested.razor:
@implements IDisposable
@inject StateContainer StateContainer
<h2>Nested component</h2>
<p>Nested component Property: <b>@StateContainer.Property</b></p>
<p>
<button @onclick="ChangePropertyValue">
Change the Property from the Nested component
</button>
</p>
@code {
protected override void OnInitialized()
{
StateContainer.OnChange += StateHasChanged;
}
private void ChangePropertyValue()
{
StateContainer.Property =
$"New value set in the Nested component: {DateTime.Now}";
}
public void Dispose()
{
StateContainer.OnChange -= StateHasChanged;
}
}
StateContainerExample.razor:
@page "/state-container-example"
@implements IDisposable
@inject StateContainer StateContainer
<h1>State Container Example component</h1>
<p>State Container component Property: <b>@StateContainer.Property</b></p>
<p>
<button @onclick="ChangePropertyValue">
Change the Property from the State Container Example component
</button>
</p>
<Nested />
@code {
protected override void OnInitialized()
{
StateContainer.OnChange += StateHasChanged;
}
private void ChangePropertyValue()
{
StateContainer.Property = "New value set in the State " +
$"Container Example component: {DateTime.Now}";
}
public void Dispose()
{
StateContainer.OnChange -= StateHasChanged;
}
}
이전 구성 요소는 IDisposable을 구현하며 OnChange 대리자는 구성 요소가 삭제될 때 프레임워크에서 호출하는 Dispose 메서드에서 구독 취소됩니다. 자세한 내용은 ASP.NET Core Razor 구성 요소 삭제참조하세요.
계단식 값 및 매개 변수
상위 구성 요소에서 하위 구성 요소로 데이터를 전달하여 연계 Razor를 사용하여 상태를 관리합니다.
- 여러 구성 요소에서 상태를 사용하려는 경우
- 유지할 최상위 상태 개체가 하나뿐인 경우
루트 수준의 연계 값 CascadingValueSource<TValue>은 변경된 연계 값을 Razor 구성 요소 구독자에게 알림할 수 있도록 허용합니다. 자세한 내용 및 작업 예제는 NotifyingDalekBlazor 예제를 참조하세요.
외부 Blazor의 동기화 컨텍스트에서 상태 수정 지원
사용자 지정 상태 관리 서비스를 사용할 때 외부 Blazor동기화 컨텍스트(예: 타이머나 백그라운드 서비스)에서 상태 수정을 지원하려면, 모든 소비 구성 요소가 StateHasChanged 호출을 ComponentBase.InvokeAsync로 래핑해야 합니다. 이렇게 하면 렌더러의 동기화 컨텍스트에서 변경 알림이 처리됩니다.
상태 관리 서비스가 StateHasChanged에서 동기화 컨텍스트를 Blazor를 호출하지 않으면 다음 오류가 발생합니다.
System.InvalidOperationException: '현재 스레드가 Dispatcher와 연결되어 있지 않습니다. InvokeAsync()를 사용하여 렌더링 또는 구성 요소 상태를 트리거할 때 Dispatcher를 실행 상태로 전환합니다.'
이 오류를 해결하는 방법에 대한 자세한 내용과 예제는 ASP.NET Core Razor 구성 요소 렌더링을 참조하세요.
ASP.NET Core