こんにちは!
Angularにおけるコンポーネントのライフサイクルで重要な役割を果たすngOnChanges
。
Angularを触っていると、このような疑問を持つ方もいるのではないでしょうか。
この記事では、ngOnChanges
の基本的な使い方から、具体的なユースケース、さらにngOnChanges
を使う際の注意点まで、詳しくご紹介します。
この記事は次のような人におすすめです。
- Angularのコンポーネントライフサイクルについて学びたい
ngOnChanges
の具体的な使い方を知りたい- コンポーネントの入力プロパティの変化に反応させたい
ngOnChanges
を使う上での注意点を知りたい
この記事を読めば、ngOnChanges
の理解が深まり、Angularコンポーネントをより効果的に使いこなせるようになるでしょう。さらに、コンポーネントのパフォーマンスを最適化するためのヒントもお伝えします。
「Angularを始めたばかりの方」「コンポーネントのライフサイクルについて詳しく知りたい方」は、ぜひ参考にしてください。
それでは、順を追って詳しく見ていきましょう!
そもそもngOnChangesとは?
まずは、ngOnChanges
の基本的な役割についておさらいしましょう。
ngOnChanges
は、Angularのコンポーネントライフサイクルインターフェースの一つで、コンポーネントの入力プロパティ(@Input
デコレータで定義されたプロパティ)の値が変化した際に実行されるメソッドです。つまり、親コンポーネントから子コンポーネントに渡されたデータが更新された時に、その変化を検知して特定の処理を行いたい場合に利用します。
例えば、親コンポーネントから子コンポーネントへ文字列や数値、オブジェクトなどのデータを渡しているとします。親コンポーネントでこれらの値が更新されると、子コンポーネントのngOnChanges
が実行され、新しい値を受け取ることができます。このとき、以前の値と新しい値の情報がオブジェクトで提供されるため、どのような変更が加えられたのかを把握することができます。
ngOnChanges
は、コンポーネントの入力プロパティが変化するたびに実行されるため、変更検知を細かくコントロールするために非常に重要なライフサイクルメソッドと言えます。
なぜngOnChangesが必要なのか?
Angularでコンポーネントのプロパティの変化を検知する方法はいくつかありますが、なぜngOnChanges
が特別なのでしょうか。ngOnChanges
の必要性について詳しく見ていきましょう。
1. 特定の入力プロパティの変化を監視できる
Angularの変更検知メカニズムは非常に効率的ですが、すべてのコンポーネントを監視しているため、変更があった場合に特定の処理だけを実行するということが難しいです。ngOnChanges
は、入力プロパティに限定して、その変化を検知できるため、必要な処理だけをピンポイントで実行できます。これにより、不必要な処理を減らし、コンポーネントのパフォーマンスを向上させることが可能です。
2. 以前の値と新しい値の両方を把握できる
ngOnChanges
の引数として渡されるオブジェクトには、変更されたプロパティ名とその以前の値と新しい値が格納されています。これにより、「どのような変化が起きたのか」を詳細に把握し、柔軟な対応が可能になります。例えば、ある入力プロパティの値が特定の条件を満たしたときだけ特定の処理を実行したい場合に便利です。
3. 初期化時の値を考慮できる
コンポーネントが最初に生成されたときも、ngOnChanges
は実行されます。この時、以前の値(previousValue)はundefined
となるため、初回時と2回目以降の変化時で処理を分けることが可能です。これにより、初回時のみ特別な処理を行うなど、より柔軟なコントロールを実現できます。
4. 複雑なオブジェクトの変化を効率的に扱える
JavaScriptのオブジェクトや配列などの参照型データが入力プロパティの場合、その内部の要素が変更されたとしても、Angularは変更を検知しない場合があります。しかし、ngOnChanges
を利用することで、親コンポーネントで新しいオブジェクトがセットされた場合に、その変化を検知することができます。
これらの理由から、ngOnChanges
はコンポーネントの入力プロパティの変化に対応するために非常に重要な役割を果たしていると言えます。
ngOnChangesの使い方
ngOnChanges
の基本的な使い方について、コード例を交えながら詳しく解説していきます。
まずは、ngOnChanges
を使うための基本的な構文を確認しましょう。ngOnChanges
はOnChanges
インターフェースを実装する必要があるため、下記のようにコンポーネントクラスに定義します。
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<p>変更前: {{ previousName }}</p>
<p>変更後: {{ currentName }}</p>
<p>{{ message }}</p>
`,
})
export class ChildComponent implements OnChanges {
@Input() name: string = '';
previousName: string = '';
currentName: string = '';
message: string = '';
ngOnChanges(changes: SimpleChanges): void {
// changesオブジェクトの確認
console.log(changes)
if(changes['name']) {
this.previousName = changes['name'].previousValue;
this.currentName = changes['name'].currentValue;
if(changes['name'].isFirstChange()){
this.message = '初めてnameプロパティの値がセットされました。'
}else{
this.message = 'nameプロパティの値が変更されました。';
}
}
}
}
上記のコードでは、ChildComponent
は親コンポーネントからname
という入力プロパティを受け取っています。ngOnChanges
メソッド内では、引数としてSimpleChanges
型のオブジェクトchanges
を受け取ります。
changes
オブジェクトは、変更された入力プロパティの情報を保持しており、以下のような構造になっています。
{
プロパティ名: SimpleChangeオブジェクト
}
それぞれのプロパティに対して、以下のような情報がSimpleChange
オブジェクトに格納されています。
プロパティ | 説明 |
---|---|
previousValue | 変更前のプロパティの値(初回の場合は undefined ) |
currentValue | 変更後のプロパティの値 |
firstChange | 初回変更の場合はtrue 、それ以外はfalse |
isFirstChange() | 初回変更の場合はtrue 、それ以外はfalse を返すメソッド |
ngOnChanges
内では、まず、変更されたプロパティの名前をチェックして処理を分岐します。changes['name']
で、name
プロパティに変更があったかどうかを確認できます。
プロパティ名が存在する場合は、previousValue
で変更前の値を、currentValue
で変更後の値をそれぞれ取得することができます。また、初回変更時のみ実行したい処理はisFirstChange()
で確認することができます。
このようにngOnChanges
を用いることで、プロパティの変化に応じた柔軟な処理を行うことができます。
次に、このChildComponent
を使用する親コンポーネント(ParentComponent
)の例を示します。
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<input type="text" [(ngModel)]="userName">
<app-child [name]="userName"></app-child>
`,
})
export class ParentComponent {
userName: string = 'initial name';
}
この例では、テキスト入力欄の値をuserName
プロパティにバインドしています。この値が変化するたびに、子コンポーネントであるChildComponent
のname
プロパティが更新され、その結果、ChildComponent
のngOnChanges
が実行されることになります。
ngOnChanges
を使うことで、親コンポーネントからのデータ更新に対して子コンポーネントで必要な処理を行うことができます。例えば、データの変換、バリデーション、UIの更新など、具体的なユースケースに応じて柔軟に対応することができます。
ngOnChangesの具体的なユースケース
ngOnChanges
がどのように役立つのか、具体的なユースケースを通して見ていきましょう。
フォームデータの初期化
子コンポーネントでフォームを使用する場合、親コンポーネントから受け取ったデータを基にフォームを初期化したい場合があります。ngOnChanges
はこのような場合にも役立ちます。
例えば、親コンポーネントからuserData
オブジェクトを受け取り、その値をフォームにセットする場合を考えてみましょう。
ngOnChanges(changes: SimpleChanges): void {
if (changes['userData'] && changes['userData'].currentValue) {
const userData = changes['userData'].currentValue;
this.userForm.patchValue({
name: userData.name,
email: userData.email,
age: userData.age
});
}
}
上記のコードでは、親コンポーネントから受け取ったuserData
をもとに、userForm
の各フィールドを初期化しています。patchValue
を使うことで、フォームの値を部分的に更新できます。初回表示時はもちろん、親コンポーネント側でデータが変更された時も、フォームの値が自動的に更新されるようになります。ngOnChanges
を利用することで、常に親コンポーネントから受け取った最新のデータに基づいてフォームを初期化することができます。
データ変換
親コンポーネントから渡されたデータを、子コンポーネントで表示しやすい形式に変換したい場合があります。
ngOnChanges(changes: SimpleChanges): void {
if (changes['data'] && changes['data'].currentValue) {
const receivedData = changes['data'].currentValue;
// Dateオブジェクトの場合フォーマットする
if (receivedData instanceof Date) {
this.formattedData = formatDate(receivedData, 'yyyy年MM月dd日', 'en-US')
}else if(typeof receivedData === 'number'){
// 数値型の場合3桁区切りにする
this.formattedData = receivedData.toLocaleString()
}else if (typeof receivedData === 'string'){
this.formattedData = receivedData.toUpperCase();
}
}
}
上記の例では、data
プロパティとして様々な型のデータを受け取った場合に、それらをフォーマットして表示用のformattedData
に変換しています。ngOnChanges
を使用することで、親コンポーネントから送られてくるデータの型や内容を考慮しつつ、適切に値を変換することができます。
入力値のバリデーション
入力プロパティとして受け取った値が、正しい範囲や形式であるかどうかをチェックする必要がある場合があります。
ngOnChanges(changes: SimpleChanges): void {
if (changes['age']) {
const currentAge = changes['age'].currentValue;
if (typeof currentAge === 'number') {
if (currentAge < 0 || currentAge > 150) {
this.errorMessage = '年齢は0〜150の範囲で入力してください';
this.validatedAge = 0;
} else {
this.errorMessage = '';
this.validatedAge = currentAge
}
} else {
this.errorMessage = '年齢は数値で入力してください';
this.validatedAge = 0
}
}
}
このコードでは、入力されたage
プロパティが0〜150の数値かどうかを検証し、不正な値が入力された場合は、エラーメッセージを表示しています。入力された年齢は、不正な値であれば0
に変更されて出力されるため、想定外の値が出力されてしまうといったリスクを回避することができます。
複雑なオブジェクトの監視
入力プロパティが配列やオブジェクトである場合、その内部の値が変更されてもngOnChanges
は実行されません。しかし、親コンポーネントで新しいオブジェクトが代入された場合にはngOnChanges
が実行されます。この特徴を利用して、オブジェクト内のデータの変更に反応する処理を書くことが可能です。
例えば、親コンポーネントから以下のようなオブジェクトを子コンポーネントに渡す場合を考えます。
interface Item{
name: string,
price: number,
quantity: number
}
親コンポーネントでItemオブジェクトを作成し、子コンポーネントに渡します。
// 親コンポーネント
item : Item = {name:'itemA',price:1000, quantity:1 }
this.item.quantity = 5; // これは子コンポーネントでは検知されない
this.item = {name:'itemA',price:1000, quantity: 5} // この場合は子コンポーネントで検知される
このとき、オブジェクトのプロパティを更新しただけでは子コンポーネントのngOnChanges
は実行されませんが、新しいオブジェクトを代入した場合はngOnChanges
が実行されるため、新しい値を元に処理を行うことができます。
ngOnChanges(changes: SimpleChanges): void {
if(changes['item']) {
const currentItem = changes['item'].currentValue;
this.totalPrice = currentItem.price * currentItem.quantity;
}
}
このコードでは、親コンポーネントからitem
プロパティを受け取り、そのprice
とquantity
を乗算したtotalPrice
を計算しています。このように、ngOnChanges
はオブジェクトの変更を監視し、変更があった時にのみ再計算などの処理を実行する際に役立ちます。
条件付きのスタイル変更
入力プロパティの値に応じて、コンポーネントのスタイルを動的に変更したい場合があります。ngOnChanges
を使うと、特定の条件が満たされたときにスタイルを適用することができます。
例えば、親コンポーネントから渡されたstatus
プロパティに応じて、背景色を変えたいとします。
ngOnChanges(changes: SimpleChanges): void {
if (changes['status']) {
const currentStatus = changes['status'].currentValue;
if (currentStatus === 'active') {
this.elementRef.nativeElement.style.backgroundColor = 'lightgreen';
} else if (currentStatus === 'inactive') {
this.elementRef.nativeElement.style.backgroundColor = 'lightgray';
}else {
this.elementRef.nativeElement.style.backgroundColor = 'white';
}
}
}
上記のコードでは、status
プロパティの値がactive
であれば背景色をlightgreen
に、inactive
であれば背景色をlightgray
に、それ以外であればwhite
に変更しています。このように、ngOnChanges
を使うことで、入力プロパティの値の変化に応じてコンポーネントのスタイルを動的に切り替えることができます。
このように、ngOnChanges
はさまざまなユースケースで非常に便利な機能を提供します。適切なタイミングで適切にngOnChanges
を使うことで、コンポーネントの動作をより柔軟に制御できるようになるでしょう。
ngOnChangesを使う上での注意点
ngOnChanges
は非常に便利な機能ですが、使用する際にはいくつかの注意点があります。
1. パフォーマンスへの影響を考慮する
ngOnChanges
は入力プロパティが変化するたびに実行されるため、処理内容によってはコンポーネントのパフォーマンスに影響を与える可能性があります。特に、複雑な処理や時間がかかる処理をngOnChanges
内で行うのは避けましょう。例えば、APIへのアクセス、巨大なデータの計算などをngOnChanges
で行う場合は、処理が終わるまでUIがフリーズしたり、表示が遅延してしまう可能性があります。もし時間がかかる処理を行いたい場合は、別途Observableを使用するなどの対応を検討しましょう。
2. SimpleChanges
オブジェクトの構造を理解する
SimpleChanges
オブジェクトは、変更されたプロパティとそのpreviousValue
, currentValue
を含むオブジェクトです。プロパティが存在する場合としない場合、またpreviousValue
がundefinedとなる場合があることに注意しましょう。必ずプロパティの存在をチェックするように記述する必要があります。プロパティが存在しない場合にchanges['name'].currentValue
といった記述をすると、エラーになってしまうので注意が必要です。
3. オブジェクトの変化に対する理解
入力プロパティが配列やオブジェクトの場合、そのプロパティの中身が変化しても、ngOnChanges
は実行されません。なぜなら、Angularは参照型の変更を検知する際には、新しいオブジェクトが代入された時のみ変更があったと認識するからです。ngOnChanges
が実行されるのは、親コンポーネントがオブジェクト自体を新しく再生成し、子コンポーネントに代入した場合のみです。もしオブジェクトの中身が変化するごとに検知したい場合は、Immutableなオブジェクトを使い、ngOnChanges
に依存しない変更検知の仕組みや、別の方法を利用する必要があります。
4. 初回実行の考慮
コンポーネントが初めて生成されたときにもngOnChanges
が実行されるため、previousValue
が undefined
になる可能性があります。初回実行と更新時で処理を分ける必要がある場合は、isFirstChange()
を利用して分岐させることが重要です。
これらの注意点を理解した上でngOnChanges
を使うことで、より安定したコンポーネントを実装できるでしょう。また、不必要にngOnChanges
に依存せず、変更検知戦略や、Observable
を活用した処理などを適切に利用することで、Angularコンポーネントをさらに使いこなせるはずです。
ひとつひとつ真摯に向き合う企業

株式会社 ONE WEDGEでは、新たな仲間を募集しています!
私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。
- 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
- 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇)を完備!
- 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
- 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
- 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
- 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
- ワークライフバランスを重視し、副業もOK!
株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!
ホームページ、採用情報は下記ボタンからご確認ください!
応募、ご質問など、LINEでお気軽にご相談ください♪
まとめ
ここまで、AngularのngOnChanges
について詳しく解説してきました。改めて、重要なポイントをおさらいしましょう。
ngOnChanges
は入力プロパティの値が変化した際に実行されるメソッド- 変更前の値と変更後の値を
SimpleChanges
オブジェクトを通して確認できる - 特定のプロパティの変化を監視したり、データの変換やバリデーション処理に使用できる
- オブジェクトの場合は新しいオブジェクトが代入された場合のみ実行される
- パフォーマンスを意識し、適切な箇所で使用する必要がある
ngOnChanges
は、Angularのコンポーネント開発において、非常に強力なツールです。ngOnChanges
を使いこなすことで、コンポーネントの再利用性を高め、より柔軟なコンポーネント開発ができるようになります。
ngOnChanges
は少し難しい概念かもしれませんが、理解することでAngular開発における選択肢が大きく広がります。焦らず一つずつ丁寧に理解していきましょう。
今回ご紹介した内容を参考に、ぜひngOnChanges
を使いこなしてみてください!