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?

More than 3 years have passed since last update.

Angular x NGXS アプリに、ngxs-labs/emitter を導入する

Posted at

背景

Angular の状態管理ライブラリ NGXS について、Action 定義を省略する手法として ngxs-labs/emitter というものがあるようなので、こちらを導入してみる。

ngxs-labs/emitter のメリットについて

ドキュメントを読むと、

  • state で直接、 actions を登録するデコレーターを使える
  • プロジェクト内で actions を作る必要がなくなる (本当に必要になるまでは)

ということなので、 actions を丸っと削除できるようだ。

イメージは下記画像のようになる。

redux-er.png

Action がなくなるので、かなりスッキリしそうな予感。

インストール

bash
npm install @ngxs-labs/emitter
# or if you use yarn
yarn add @ngxs-labs/emitter

AppModule にインポート

src/app/app.module.ts
...
import { NgxsModule }              from '@ngxs/store';
import { NgxsEmitPluginModule }    from '@ngxs-labs/emitter';

...

@NgModule({
  ...
  imports: [
    ...
    NgxsModule.forRoot(...),
    NgxsEmitPluginModule.forRoot()
  ],
  ...
})
export class AppModule { }

レシーバー

レシーバーは基本的な構成要素。
@Receiver() は state 内の静的メソッドをデコレートできる関数で、そのメソッドをエミッターに渡す。

src/app/auth/auth.state.ts
import { Injectable }                    from '@angular/core';
import { Receiver }                      from '@ngxs-labs/emitter';
import { Selector, State, StateContext } from '@ngxs/store';

export interface AuthStateModel {
  isAuthenticated: boolean;
}

@State<AuthStateModel>({
  name: 'auth',
  defaults: {
    isAuthenticated: false
  }
})
@Injectable()
export class AuthState {

  @Receiver()
  static setAuthenticated(ctx: StateContext<AuthStateModel>) {
    ctx.setState({
      isAuthenticated: true
    });
  }

  @Receiver()
  static setUnauthenticated(ctx: StateContext<AuthStateModel>) {
    ctx.setState({
      isAuthenticated: false
    });
  }

  ...
}

エミッター

エミッターは、基本的にコンポーネントとレシーバーの間の橋渡しをするもの。
@Emitter() は、新しいゲッターを定義するプロパティを修飾する関数で、
、エミッタブルなインターフェースにアクセスできるようにする。

src/app/auth/auth.state.ts
import { Injectable }                                  from '@angular/core';
import { Emittable, Emitter, EmitterAction, Receiver } from '@ngxs-labs/emitter';
import { Selector, State, StateContext }               from '@ngxs/store';

// import { AuthAction } from './auth.actions';

export interface AuthStateModel {
  isAuthenticated: boolean;
}

@State<AuthStateModel>({
  name: 'auth',
  defaults: {
    isAuthenticated: false
  }
})
@Injectable()
export class AuthState {

  @Emitter(AuthState.setAuthenticated)   static actSetAuthenticated: Emittable<void>;
  @Emitter(AuthState.setUnauthenticated) static actSetUnauthenticated: Emittable<void>;

  @Receiver()
  static setAuthenticated(
    ctx:    StateContext<AuthStateModel>,
    action: EmitterAction<void>
  ) {
    ctx.setState({
      isAuthenticated: true
    });
  }

  @Receiver()
  static setUnauthenticated(
    ctx:    StateContext<AuthStateModel>,
    action: EmitterAction<void>
  ) {
    ctx.setState({
      isAuthenticated: false
    });
  }

  @Selector()
  static getIsAuth(state: AuthStateModel) {
    return state.isAuthenticated;
  }
}
src/app/auth/auth.service.ts
...
import { AuthState } from './auth.state';

@Injectable()
export class AuthService {

  ...

  initAuthListener() {
    this.afAuth.authState.subscribe(user => {
      if (user) {
        AuthState.actSetAuthenticated.emit();
        ...
      } else {
        ...
        AuthState.actSetUnauthenticated.emit();
        ...
      }
    });
  }

  ...

}

感想

  • かなりシンプルに書ける
    • 例えば、dispatch と書いていたところを emit で書くと、分かりやすく、かつ短く書ける
  • 無駄な action ファイルが不要でディレクトリが綺麗になる

実務でも使ってたが、より知見が深まった気がする。

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?