Angular PR

【Angular】ngOnChangesってなに?必ず知っておくべき使い方と注意点

【Angular】ngOnChangesってなに?必ず知っておくべき使い方と注意点
記事内に商品プロモーションを含む場合があります

こんにちは!

Angularにおけるコンポーネントのライフサイクルで重要な役割を果たすngOnChanges

ngOnChangesっていつ使うんだろう?
使いどころがよくわからない。
もっと具体的に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を使うための基本的な構文を確認しましょう。ngOnChangesOnChangesインターフェースを実装する必要があるため、下記のようにコンポーネントクラスに定義します。

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プロパティにバインドしています。この値が変化するたびに、子コンポーネントであるChildComponentnameプロパティが更新され、その結果、ChildComponentngOnChangesが実行されることになります。

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プロパティを受け取り、そのpricequantityを乗算した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が実行されるため、previousValueundefinedになる可能性があります。初回実行と更新時で処理を分ける必要がある場合は、isFirstChange()を利用して分岐させることが重要です。

これらの注意点を理解した上でngOnChangesを使うことで、より安定したコンポーネントを実装できるでしょう。また、不必要にngOnChangesに依存せず、変更検知戦略や、Observableを活用した処理などを適切に利用することで、Angularコンポーネントをさらに使いこなせるはずです。

キャリア形成/給与還元
ひとつひとつ真摯に向き合う企業
ONE_WEDGE社員募集

株式会社 ONE WEDGEでは、新たな仲間を募集しています!

私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。

  • 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
  • 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇)を完備!
  • 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
  • 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
  • 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
  • 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
  • ワークライフバランスを重視し、副業もOK!

株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!

ホームページ、採用情報は下記ボタンからご確認ください!

応募、ご質問など、LINEでお気軽にご相談ください♪

まとめ

ここまで、AngularのngOnChangesについて詳しく解説してきました。改めて、重要なポイントをおさらいしましょう。

  • ngOnChangesは入力プロパティの値が変化した際に実行されるメソッド
  • 変更前の値と変更後の値を SimpleChangesオブジェクトを通して確認できる
  • 特定のプロパティの変化を監視したり、データの変換やバリデーション処理に使用できる
  • オブジェクトの場合は新しいオブジェクトが代入された場合のみ実行される
  • パフォーマンスを意識し、適切な箇所で使用する必要がある

ngOnChangesは、Angularのコンポーネント開発において、非常に強力なツールです。ngOnChangesを使いこなすことで、コンポーネントの再利用性を高め、より柔軟なコンポーネント開発ができるようになります。

ngOnChangesは少し難しい概念かもしれませんが、理解することでAngular開発における選択肢が大きく広がります。焦らず一つずつ丁寧に理解していきましょう。

今回ご紹介した内容を参考に、ぜひngOnChangesを使いこなしてみてください!

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です