Blazor コンポーネント ライフサイクルを理解する
Blazor コンポーネントには明確に定義されたライフサイクルがあります。それは最初に作成されたときに始まり、破棄されたときに終了します。 コンポーネントのライフサイクルは、特定のトリガーに応答して発生する一連のイベントによって管理されます。 このようなトリガーには、コンポーネントの初期化、ユーザーとコンポーネントの対話、コンポーネントが存在するページの終了などが含まれます。
このユニットでは、Blazor コンポーネントのライフサイクル中に発生するイベントについて学習します。 これらのイベントを処理して、行われる作業を最適化し、Blazor ページの応答性を向上させる方法を確認します。
Blazor コンポーネント ライフサイクル
Blazor コンポーネントは Blazor アプリのビューを表し、これによりレイアウトと UI ロジックが定義されます。 コンポーネントによって、アプリの実行時に HTML マークアップが生成されます。 ユーザーとの対話イベントによってカスタム コードをトリガーでき、コンポーネントを更新して表示を再レンダリングできます。 ページを閉じると、Blazor によってコンポーネントが削除され、すべてのリソースがクリーンアップされます。 ユーザーがページに戻ると、新しいインスタンスが作成されます。
次の図は、コンポーネントの有効期間中に発生するイベントと、これらのイベントを処理するために使用できるメソッドを示しています。 SetParametersAsync
を除き、Blazor には、各メソッドの同期および非同期の両方のバージョンが用意されています。
すべての Blazor コンポーネントは、示されているメソッドを定義し、既定の動作を提供する、ComponentBase クラスまたは IComponent から派生します。 イベントは、対応するメソッドをオーバーライドすることによって処理します。
この図は、ライフサイクル メソッド間にシングルスレッド フローが存在することを示していますが、これらのメソッドの非同期バージョンを使用すると Blazor アプリでレンダリング プロセスを迅速化できます。 たとえば、SetParametersAsync
で最初の await
が発生したとき、Blazor コンポーネントで OnInitialized
および OnInitializedAsync
メソッドが実行されます。 待機中のステートメントが完了すると、SetParametersAsync
内の実行スレッドが再開されます。
この同じロジックが、一連のライフサイクル メソッドの全体にわたって適用されます。 また、OnInitializedAsync
と OnParametersSetAsync
の処理中に発生する各 await
操作は、そのコンポーネントの状態が変更されたことを示しており、ページの即時レンダリングをトリガーできます。 初期化が完全に完了する前に、ページが複数回レンダリングされる可能性があります。
ライフサイクル メソッドを理解する
コンポーネント ライフサイクルの各メソッドには特定の目的があり、メソッドをオーバーライドしてコンポーネントにカスタム ロジックを追加できます。 次の表では、ライフサイクル メソッドを発生する順に一覧表示し、その目的について説明しています。
注文 | ライフサイクル メソッド | 説明 |
---|---|---|
1 | コンポーネントの作成 | コンポーネントがインスタンス化されます。 |
2 | SetParametersAsync | レンダリング ツリー内のコンポーネントの親からパラメーターを設定します。 |
3 | OnInitialized / OnInitializedAsync | コンポーネントを開始する準備ができると発生します。 |
4 | OnParametersSet / OnParametersSetAsync | コンポーネントがパラメーターを受け取り、プロパティが割り当てられると発生します。 |
5 | OnAfterRender / OnAfterRenderAsync | コンポーネントがレンダリングされた後に発生します。 |
6 | Dispose / DisposeAsync |
コンポーネントが IDisposable または IAsyncDisposable を実装している場合、コンポーネントを破棄する一環として適切な破棄が行われます。 |
SetParametersAsync メソッド
Blazor コンポーネントが含まれているページにユーザーがアクセスすると、Blazor ランタイムによってそのコンポーネントの新しいインスタンスが作成され、既定のコンストラクターが実行されます。 コンポーネントが構築されると、Blazor ランタイムによって SetParametersAsync
メソッドが呼び出されます。
コンポーネントでパラメーターが定義されている場合は、Blazor ランタイムによって、これらのパラメーターの値が呼び出し元の環境からそのコンポーネントに挿入されます。 これらのパラメーターは ParameterView
オブジェクトに含まれており、SetParametersAsync
メソッドからアクセスできるようになります。 これらの値をコンポーネントの Parameter
プロパティに入力するには、base.SetParametersAsync
メソッドを呼び出します。
または、これらのパラメーターを別の方法で処理する必要がある場合は、このメソッドでそれを行います。 たとえば、コンポーネントに渡されたすべてのパラメーターの使用前の検証が必要になることがあります。
Note
SetParametersAsync
メソッドは、コンポーネントにパラメーターがない場合でも、そのコンポーネントが作成されたときに常に実行されます。
OnInitialized および OnInitializedAsync メソッド
OnInitialized
および OnInitializedAsync
メソッドをオーバーライドして、カスタム機能を追加することができます。 これらは、SetParametersAsync
メソッドによってコンポーネントのパラメーターベースのプロパティ (ParameterAttribute または CascadingParameterAttribute の属性が設定されている) が設定された後に実行されます。 これらのメソッドで初期化ロジックを実行します。
アプリケーションの render-mode
プロパティが Server
に設定されている場合、OnInitialized
および OnInitializedAsync
メソッドはコンポーネント インスタンスに対して一度だけ実行されます。 コンポーネント パラメーターがそのコンポーネントの親によって変更された場合、SetParametersAsync
メソッドはもう一度実行されますが、これらのメソッドは実行されません。 パラメーターが変更されたときにコンポーネントを再初期化する必要がある場合は、SetParametersAsync
メソッドを使用します。 初期化を 1 回実行したい場合は、これらのメソッドを使用します。
render-mode
プロパティが ServerPrerendered に設定されている場合、OnInitialized
および OnInitializedAsync
メソッドは 2 回実行されます。静的なページ出力を生成するプリレンダリング フェーズ中に 1 回と、サーバーでブラウザーとの SignalR 接続が確立されたときにもう 1 回です。 これらのメソッドでは、Blazor コンポーネントの状態を設定するために使用するデータを Web サービスから取得するなど、コストのかかる初期化タスクを実行する場合があります。 この場合は、最初の実行中に状態情報をキャッシュし、保存された状態を 2 回目の実行中に再利用します。
Blazor コンポーネントによって使用される依存関係はすべて、このインスタンスが作成されたとき、OnInitialized
または OnInitializedAsync
メソッドが実行される前に挿入されます。 これらの依存関係によって挿入されたオブジェクトは OnInitialized
または OnInitializedAsync
メソッドで使用できますが、その前には使用できません。
重要
Blazor コンポーネントでは、コンストラクターの依存関係の挿入がサポートされていません。 代わりに、コンポーネント マークアップで @inject
ディレクティブを使用するか、プロパティ宣言で InjectAttribute を使用します。
プリレンダリング フェーズ中に、Blazor Server コンポーネント内のコードで、ブラウザーへの接続が必要なアクション (JavaScript コードの呼び出しなど) を実行することはできません。 ブラウザーとの接続に依存するロジックは、OnAfterRender
または OnAfterRenderAsync
メソッドに配置する必要があります。
OnParametersSet および OnParametersSetAsync メソッド
OnParametersSet
および OnParametersSetAsync
メソッドは、コンポーネントが初めてレンダリングされる場合は OnInitialized
メソッドまたは OnInitializedAsync
メソッドの後に、それ以降にレンダリングされる場合は SetParametersAsync
メソッドの後に実行されます。 SetParametersAsync
と同様に、これらのメソッドは、コンポーネントにパラメーターがない場合でも常に呼び出されます。
いずれかのメソッドを使用して、コンポーネント パラメーター値に依存する初期化タスク (計算されるプロパティの値の計算など) を完了します。 コンストラクターでは、このような実行時間の長い操作を行わないでください。 コンストラクターは同期的であるため、実行時間の長い操作の完了を待っていると、そのコンポーネントを含むページの応答性に影響を与えます。
OnAfterRender および OnAfterRenderAsync メソッド
OnAfterRender
メソッドと OnAfterRenderAsync
メソッドは、Blazor ランタイムで、ユーザー インターフェイスのコンポーネントによって表されるビューの更新が必要になるたびに実行されます。 この状態は、次の場合に自動的に発生します。
- コンポーネントの状態が変化する (たとえば、
OnInitialized
またはOnInitializedAsync
メソッドあるいはOnParametersSet
およびOnParametersSetAsync
メソッドが実行されたとき)。 - UI イベントがトリガーされる。
- アプリケーション コードでこのコンポーネントの
StateHasChanged
メソッドを呼び出す。
外部イベント、UI トリガーのいずれかから StateHasChanged が呼び出されると、コンポーネントは条件付きで再レンダリングされます。 次の一覧では、StateHasChanged
とその後に続くメソッド呼び出しの順序を詳しく説明しています。
- StateHasChanged: コンポーネントは、再レンダリングが必要であるとマークされます。
- ShouldRender: コンポーネントをレンダリングする必要があるかどうかを示すフラグを返します。
- BuildRenderTree: コンポーネントをレンダリングします。
StateHasChanged
メソッドでは、このコンポーネントの ShouldRender
メソッドを呼び出します。 このメソッドの目的は、状態の変更によってコンポーネントでのビューのレンダリングが必要になったかどうかを判定することです。 既定では、すべての状態変更でレンダリング操作がトリガーされますが、ShouldRender
メソッドをオーバーライドして意思決定ロジックを定義することができます。 ShouldRender
メソッドは、ビューを再びレンダリングする必要がある場合は true
を、それ以外の場合は false
を返します。
このコンポーネントにレンダリングが必要な場合は、ブラウザーでの UI の表示に使用される DOM のバージョンを更新できるモデルを生成するために BuildRenderTree
メソッドを使用できます。 ComponentBase
クラスによって提供される既定のメソッド実装を使用するか、または固有の要件がある場合はカスタム ロジックでそれをオーバーライドできます。
次に、コンポーネント ビューがレンダリングされ、UI が更新されます。 最後に、このコンポーネントでは OnAfterRender
および OnAfterRenderAsync
メソッドを実行します。 この時点では、UI が完全に機能しており、JavaScript や DOM 内のすべての要素を操作できます。 これらのメソッドを使用して、JS 相互運用から JavaScript コードを呼び出すなどの、完全にレンダリングされたコンテンツへのアクセスを必要とするその他のすべての手順を実行します。
OnAfterRender
および OnAfterRenderAsync
メソッドは、firstRender
という名前のブール値のパラメーターを受け取ります。 このパラメーターは、そのメソッドが初めて実行されるときは true
ですが、それ以降は false
です。 このパラメーターを評価すれば、コンポーネントがレンダリングされるたびに繰り返すには無駄で、リソースを消費しすぎる可能性のある 1 回限りの操作を実行できます。
Note
プリレンダリングを Blazor コンポーネントの最初のレンダリングと混同しないでください。 プリレンダリングは、ブラウザーとの SignalR 接続が確立される前に発生し、ページの静的バージョンを生成します。 最初のレンダリングは、ブラウザーとの接続が完全にアクティブであり、すべての機能が使用可能なときに発生します。
Dispose および DisposeAsync メソッド
他のすべての .NET クラスと同様に、Blazor コンポーネントではマネージド リソースとアンマネージ リソースを使用できます。 マネージド リソースは、ランタイムによって自動的に再利用されます。 しかし、アンマネージ リソースを解放するには、IDisposable
または IAsyncDisposable
インターフェイスを実装し、Dispose
または DisposeAsync
メソッドを提供する必要があります。 この方法により、サーバー内でのメモリ リークの可能性が低下します。
ライフサイクル メソッドで例外を処理する
Blazor コンポーネントのライフサイクル メソッドは、失敗するとブラウザーへの SignalR 接続を閉じ、それによって Blazor アプリの機能が停止されます。 この結果を防ぐには、ライフサイクル メソッドのロジックの一部として、例外を処理する準備をするようにしてください。 詳細については、「ASP.NET Core Blazor アプリのエラーを処理する」を参照してください。