← Angular コース
54. 提供範囲 — root提供とコンポーネント提供
サービスのインスタンスが「どの範囲で1個か」は、どこで提供するかで決まります。@Injectable({ providedIn: 'root' }) はアプリ全体で1個の共有インスタンスです。一方、コンポーネントの providers: [CounterService] に書くと、そのコンポーネントが作られるたびに専用のインスタンスが作られ、その部品ツリーの中だけで共有されます。
使い分けの指針は「基本は root、画面ごとに独立した状態が欲しいときだけコンポーネント提供」です。たとえば同じ検索パネルを1画面に2つ置き、それぞれが別々の検索状態を持つべきなら、状態サービスをパネル側の providers に置きます。root のままだと2つのパネルが同じ状態を共有してしまいます。
つまずきやすいのは、コンポーネント提供にしたことを忘れて「別の画面で値が消えた」と混乱するケースです。コンポーネント提供のインスタンスは、そのコンポーネントが破棄されると一緒に消えます。逆に root のサービスは画面を離れても生き続けるので、状態の寿命をどちらにしたいかで選びましょう。
サンプルコード(フレームワーク環境が必要なため表示のみ)
import { Component, Injectable, inject } from '@angular/core';
// providedIn を付けない = 提供場所を providers で決めるサービス
@Injectable()
export class CounterService {
count = 0;
increment() {
this.count++;
}
}
@Component({
selector: 'app-counter-panel',
// このコンポーネントごとに専用のインスタンスが作られる
providers: [CounterService],
template:
'<button (click)="counter.increment()">+1</button>' +
' <span>{{ counter.count }}</span>',
})
export class CounterPanel {
counter = inject(CounterService);
}
// <app-counter-panel /> を2つ並べると、カウントは別々に進む
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗