0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Angular]injectって便利な罠

0
Posted at

Angularのinject、メソッド内で呼んだらNG203で怒られた話(なんで?)

Ionic+Angularでスマホアプリを作っていて、
システム全体の都合上、過去バージョンの資源(Routerで管理)もアプリ内で持っていないといけないと言う制約のため、
バージョンごとにクラスを継承に次ぐ継承を行うような形で作っていたのですが、
新しい書き方のstandaloneで作り直したら綺麗にできるのでは?という安直な考えと、
毎回overrideのconstrucor書くのがマジで面倒くさくなってきたし、
最近よく見るinject使って必要なものだけ引き継げばいいじゃんみたいなノリで書いていた時にハマったお話。

この作りが正解なのかはわからないけど、前バージョンのコードをまるっとフォルダごとコピーして変更点のある機能だけ直すみたいな、無駄なソースを量産するような作りにウンザリしていたので、class継承で必要な関数だけ直す方が良くね?ということでこんな作りにしている。

起きたこと

Angularで「constructor書きたくないな〜」と思って、最近よく見るinject()を使おうとした。

someMethod() {
  const service = inject(MyService);
  service.doSomething();
}

→ 実行

NG0203: inject() must be called from an injection context

お前、どこでも呼べるんとちゃうんかい???

結論

inject()はどこでも呼べるわけじゃない。
DIコンテキストの中でしか使えない。
(#^ω^)ピキピキ
そんなわけで、まぁ色々と調べたよ。。。

NGな例(今回のやつ)

someMethod() {
  const service = inject(MyService); // ❌ NG
}

これはただのメソッドなので、Angular的には
👉「DIの文脈じゃないよ?」って判断される

OKな使い方

① コンポーネントのフィールド初期化

private service = inject(MyService);

これはOK。なぜなら

👉 コンポーネント生成時(DIコンテキスト内)だから

② constructor(従来通り)

constructor(private service: MyService) {}

これはもちろんOK

③ factory関数(重要)

const myFactory = () => {
  const service = inject(MyService);
  return new Something(service);
};

これもOK
👉 AngularがDIとして呼び出すから

なぜダメなのか

AngularのDIは

「Angularがインスタンスを作るタイミング」でしか効かない

つまり:

  • コンポーネント生成時 → OK
  • provider解決時 → OK
  • 普通のメソッド実行 → ❌ Angular関係ない

よくある勘違い

❌ injectは便利なグローバル関数

ではない

⭕ AngularのDIライフサイクルに依存した関数

じゃあどうすりゃいいのよ?

パターン1:普通にフィールドで持つ

private service = inject(MyService);

someMethod() {
  this.service.doSomething();
}

パターン2:どうしても遅延したい場合

private _service?: MyService;

get service() {
  return this._service ??= inject(MyService);
}

※ただしこれも「呼ばれるタイミングがDIコンテキスト内であること」が前提

そもそも、なぜinjectがあるの?

  • constructorを汚したくない
  • standalone APIと相性がいい
  • 関数ベースDIを可能にする

要はコレを使うと 「Angularの設計を関数寄りにするための仕組み」 に出来るよって話。

まとめ

  • injectはどこでも使えるわけじゃない
  • AngularのDIコンテキスト内限定
  • メソッド内で呼ぶと普通に怒られる

安易に「constructor書くのダルいからinject使おう」→「どこでも呼べるやろ」みたいな発想はイケてないね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?