Blazor01

BlazorでのWebアプリケーション開発手法1【C#】B20_OnInitialized

前回のB19では OnParametersSet を扱いました。今回はコンポーネントの初期化処理を書く場所である OnInitialized を扱います。

Microsoftドキュメントで確認する

Microsoft Learn の「ASP.NET Core Razor コンポーネントのライフサイクル」ページを開き、OnInitialized(および非同期版の OnInitializedAsync)の項目を確認します。URLはボーナスレクチャーに記載されています。

図1 Microsoft Learn「ASP.NET Core Razor コンポーネントのライフサイクル」ページ

ドキュメントには、OnInitialized と OnInitializedAsync は「コンポーネントの初期化にのみ使用」し、パラメータ値やパラメータ値の変更に依存しない初期化処理はこれらのメソッドで行う、と説明されています。一方、パラメータ値やその変更がコンポーネントの状態に影響する場合は、代わりに OnParametersSet(または非同期版)を使用する、とされています。

図2 「コンポーネントの初期化(OnInitialized{Async})」の解説部分

Clearメソッドを作ってOnInitializedから呼び出す

実演用に、計測値・計測日時・計測場所をそれぞれ初期状態の文字列へ戻す Clear メソッドを MeasurePage.razor に新規追加します。

private void Clear()
{
    _measureValue = "計測ボタンを押してください";
    _measureDate = "---";
    _measureArea = "---";
}

 

図3 Clearメソッドの実装

このメソッドを起動時に呼びたい場合、@codeブロック内で protected override void On と入力すると、IntelliSenseの候補に OnInitialized() や OnInitializedAsync() などのオーバーライド候補が表示されます。

図4 「protected override on」と入力した際のIntelliSense候補一覧

候補から OnInitialized() を選択して自動生成し、中で Clear() を呼び出すよう実装します。

protected override void OnInitialized()
{
    Clear();
}

図5 OnInitializedからClear()を呼び出す実装

実行すると、OnInitialized が動くタイミングで Clear が呼ばれるため、計測画面を開いた時点で計測値・計測日時・計測場所が初期値(「計測ボタンを押してください」「—」「—」)で表示されることを確認できます。

時間のかかる初期化処理は非同期版を使う

起動時にデータベース検索など時間のかかる処理を行う場合は、非同期版の OnInitializedAsync を使います。同様にIntelliSenseの候補から選択すると、既定の実装(base.OnInitializedAsync() を返すだけの雛形)が自動生成されます。

protected override Task OnInitializedAsync()
{
    return base.OnInitializedAsync();
}

図6 OnInitializedAsyncのIntelliSenseによる自動生成コード

サンプルプロジェクト標準の Weather.razor では、実際にこの OnInitializedAsync を使って非同期の読み込みをシミュレートしています。中では await Task.Delay(500) によって、時間のかかる処理を行っている想定のコードが書かれています。

図7 Weather.razorのOnInitializedAsync実装(Task.Delayで非同期読み込みをシミュレート)

初期化処理は、メモリ上の値を入れ替えるだけのような処理であれば同期版(OnInitialized)でよく、ファイルアクセスなどすぐに結果が返ってこない可能性がある処理であれば非同期版(OnInitializedAsync)を使う、という使い分けになります。

コンストラクタは基本的に使わない

Razorコンポーネントには通常のC#と同じようにコンストラクタも書けますが、基本的には使いません。理由は、コンストラクタが動く時点ではコンポーネントの初期化に必要な設定(依存性の注入やパラメータの設定)がまだ完了していないためです。

これを確認するため、@inject ディレクティブで NavigationManager を Navi という名前で注入するコードを追加し、コンストラクタと OnInitialized の両方にブレークポイントを設置してデバッグ実行します。

@inject NavigationManager Navi

 

図8 コンストラクタで停止した時点ではNaviがnullであることを確認

計測画面を開くと、まずコンストラクタでブレークし、この時点で Navi の値を確認すると null になっています。続行すると OnInitialized でブレークし、この時点では Navi に値(RemoteNavigationManager のインスタンス)がすでに入っていることが確認できます。

図9 OnInitializedで停止した時点ではNaviに値が入っていることを確認

つまり、コンストラクタの時点ではまだ依存性の注入などの準備が整っておらず、OnInitialized(またはその非同期版)に来た段階で初めて準備が整うため、初期化処理はコンストラクタではなく OnInitialized 側で行う必要があります。

参考:コンストラクタの引数で受け取る方法

Injectの仕組みだけで言えば、コンストラクタの引数として NavigationManager を受け取る書き方も可能です。この場合も依存性注入によって値を取得できますが、基本的には推奨されません。

public MeasurePage(NavigationManager navi)
{
}

図10 コンストラクタの引数でNavigationManagerを直接受け取る例

さらに、コンストラクタには非同期版が存在しないため、その意味でも初期化処理は OnInitialized もしくは OnInitializedAsync のどちらかを使うようにします。

まとめ:コンポーネントの初期化は OnInitialized(同期)または OnInitializedAsync(非同期)で行う。パラメータの値やその変更に応じた処理は OnParametersSet(またはその非同期版)を使う。コンストラクタは依存性の注入やパラメータの設定が完了する前に動くため、初期化処理には使わない。

BlazorでのWebアプリケーション開発手法1【C#】

A01_はじめに
A02_バージョンの確認
A03_プロジェクトの作成
A04_アプリの実行
A05_サンプルプログラムの構成
A06_Razorコンポーネント
A07_Razor構文
A08_@pageでURLを指定する
A09_@rendermode
A10_PageTitle
A11_HTMLの見出し
A12_pタグ
A13_単方向データバインド
A14_単方向データバインドの詳細
A15_Bootstrap
A16_ボタンクリックイベント
A17_イベント引数の受け取り方
A18_ここまでのまとめ
B01_新しいWebページを追加する方法
B02_サイドバーから画面を表示する
B03_サイドバーのアイコンを変更する方法
B04_計測値を表示する
B05_変数に置き換える
B06_最新の値でデータを更新する
B07_@usingで通常のC#コードを呼び出す
B08_画面遷移_aタグ
B09_画面遷移_aタグの見た目をボタンにする
B10_画面遷移_NavigationManagerでの遷移
B11_画面間のパラメータの受け渡し方法
B12_EscapeDataStringでエスケープする
B13_複数のパラメータを渡す
B14_任意のパラメータにする
B15_string以外の型をパラメータで使う方法
B16_DateTime型をパラメータで渡す方法
B17_引数2個のURLも型指定に変更する
B18_パラメータ属性をつけるときの注意点
B19_OnParametersSet
B20_OnInitialized
B21_OnInitializedが2回通る問題の対応
B22_ブラウザが開いている間の値を記憶する方法
B23_値の受け渡しとしてのProtectedSessionStorage
B24_非同期を想定したUIの制御
C01_一覧表示
C02_非同期での一覧表示
C03_table-striped
D01_入力エリア
D02_双方向データバインド
D03_入力データをリアルタイムで通知する方法
D04_placeholder
D05_入力エリアの横幅の調整
D06_テキストチェンジイベントを拾う方法
D07_プルダウン
D08_プルダウンのbootstrap
D09_プルダウンの選択している値をデータバインドで操作する
D10_プルダウンにリストの値を表示する
D11_プルダウンに未選択行を入れる
D12_プルダウンの入力を禁止する
D13_プルダウンのチェンジイベントを取得する
D14_チェックボックス
D15_チェックボックスにラベルを付ける
D16_複数のチェックボックスを並べる
D17_ラジオボタン
D18_ラジオボタンのデータバインド
D19_ラジオボタンのチェンジイベント
D20_ラジオボタンにbootstrapを適応する