BlazorでWeb Storageを利用して一時的にデータを保存する方法
この記事では、BlazorでWeb Storageを利用する方法について解説したいと思います。
ユーザーがリロードすると画面上の情報が失われてしまいます。その際に、データを一時的に保存しておき、状態を維持する方法を見ていきたいと思います。
本記事はQiitaのミラーです。
Web Storageとは?
HTML5で導入されたブラウザーにKey-Value形式でテキストデータを保存できる仕組みです。ブラウザーにデータを保管する仕組みとしてはCookieがありますが、Cookieよりも保存容量が大きく、常にHttp Headerで送信されるわけではなく、必要なときにだけ取り出せます。
sessionStroageとlocalStorageの2種類があり、目的に応じて使い分けができます。
-
sessionStorage
ブラウザーのタブ単位でデータを保存できます。タブを再読込してもデータは維持されますが、タブかブラウザーを閉じると、データは失われます。 -
localStorage
ブラウザー単位でデータを保存でき、タブやブラウザー本体を閉じてもデータが維持されます。再度ブラウザーを起動するとデータを再読み込みできます。
Blazor ServerでWeb Storageを利用する方法
まずは、Blazor ServerでWeb Storageを利用する方法をご紹介したいと思います。
Blazor ServerではMicrosoftが提供している、「ASP.NET Core で保護されたブラウザー ストレージ」を利用することで、簡単にデータを暗号化して保存できます。
sessionStorageの場合
@page "/countersession"
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedSessionStorage ProtectedSessionStore
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
@if (isConnected)
{
<p>Current count: <strong>@currentCount</strong></p>
<button @onclick="IncrementCount">Increment</button>
}
else
{
<p>Loading...</p>
}
@code {
private int currentCount;
private bool isConnected;
/// <summary>
/// コンポーネントのレンダリングが完了した後に呼び出されます
/// </summary>
/// <param name="firstRender"></param>
/// <returns></returns>
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
isConnected = true;
await LoadStateAsync();
StateHasChanged();
}
}
private async Task LoadStateAsync()
{
var result = await ProtectedSessionStore.GetAsync<int>("count");
currentCount = result.Success ? result.Value : 0;
}
private async Task IncrementCount()
{
currentCount++;
await ProtectedSessionStore.SetAsync("count", currentCount);
}
}
Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorageを読み込むことにより、ProtectedSessionStorageを利用できます。
sessionStorage、localStorageは、プリレンダリング中に利用できないため、OnInitializedAsyncではなく、OnAfterRenderAsyncに画面読み込み時のデータ読み取り処理を記述します。
これで画面をリロードした際も、同じタブ内であればデータを保存し、再読み込みできます。
また、データが暗号化されていることも、開発者ツールから確認できます。
localStorageの場合
ProtectedSessionStorageをProtectedLocalStorageに変更するだけです。
localStorageの場合は、ブラウザーを終了してもデータが保存されます。再度ブラウザーを起動すれば保存した値を読み込むことが可能です。localStorageに保存したデータは、有効期限がないため、システムから削除するか、ユーザーが自分で削除しない限りデータが残り続けることに注意してください。
localStorageの場合も、同様にデータが暗号化されます。
Blazor WebAssemblyでWeb Stroageを利用する方法
Blazor WebAssemblyの場合は、Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorageを利用できないため、サードパーティ製のライブラリを利用した例をご紹介します。
今回は、Blazoredというライブラリを使ってみます。(https://github.com/Blazored)
導入はNugetから、Blazored.SessionStorage、Blazored.LocalStorageを検索すると見つかります。
sessionStorageの場合
Blazored.SessionStorageを読み込み、builderにサービスを登録します。これで各Razorコンポーネントから利用できます。
using Blazored.SessionStorage;
...
builder.Services.AddBlazoredSessionStorage();
await builder.Build().RunAsync();
@page "/counter"
@inject Blazored.SessionStorage.ISessionStorageService sessionStorage
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
protected override async Task OnInitializedAsync()
{
currentCount = await sessionStorage.GetItemAsync<int>("count");
}
private void IncrementCount()
{
currentCount++;
sessionStorage.SetItemAsync("count", currentCount);
}
}
Blazor Serverの時と同様にデータの保存、読み込みができます。(Blazoredを利用した場合は、OnInitializedAsyncでも読み込みが可能なようです。)
ただし、そのままではデータの暗号化はされないので、ユーザーが自由にデータの中身を確認できる点については注意してください。
localStorageの場合
読み込むライブラリが違うだけで、ほとんど同じように実装できます。
using Blazored.LocalStorage;
using BlazorWasmBrowserStorage1;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddBlazoredLocalStorage();
await builder.Build().RunAsync();
@page "/counter"
@inject Blazored.LocalStorage.ILocalStorageService localStorage
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
protected override async Task OnInitializedAsync()
{
currentCount = await localStorage.GetItemAsync<int>("count");
}
private void IncrementCount()
{
currentCount++;
localStorage.SetItemAsync("count", currentCount);
}
}
まとめ
BlazorでWeb Storageを利用する方法をご紹介しました。
ページ遷移でデータを保持するだけであれば、サービスをDIコンテナにScopedで登録することでも対応可能ですが、ページリロード時にはデータが消失します。その場合でもデータを保持したい場合には、Web Storageを利用をご検討ください。
皆様のご参考になれば幸いです。
参考サイト
この記事は以下の情報を参考にして執筆しました。
Discussion