Upgrade to Pro — share decks privately, control downloads, hide ads and more …

NgRx v7

kou
October 19, 2018

NgRx v7

NgRxについての紹介とv7の変更点など

kou

October 19, 2018
Tweet

More Decks by kou

Other Decks in Technology

Transcript

  1. NgRxの紹介とv7について

    View full-size slide

  2. @kou
    bitbank, inc

    View full-size slide

  3. NgRxとは
    - “ Reactive libraries for Angular ”
    - Angularアプリケーションの状態管理ライブラリ
    - 似たようなもので NGXS、Akita などがある

    View full-size slide

  4. Packages
    @ngrx/store @ngrx/effects @ngrx/router-store
    @ngrx/store-devtools @ngrx/entity @ngrx/schematics

    View full-size slide

  5. https://medium.com/default-to-open/understanding-a-large-scale-angular-app-with-ngrx-80f9fc5660cc

    View full-size slide

  6. 個人的にNgRxが良いと思うところ
    - APIが低レベルで汎用的なので、柔軟性が高い
    - 開発が安定していて、コード品質も高い
    - ユーザーが多くて、イベントなどでの発表も多い
    - RxJSベストプラクティス集なので、 RxJSの秩序が守られる

    View full-size slide

  7. NgRx簡単年表
    1系 2015年12月 @ngrx/storeの公開開始
    2系 2016年05月 ngrx/example-appの追加、各パッケージの安定版
    4.0.0 2017年07月 @ngrx/entity の追加、ngrx/platform へのモノリポ移行
    5.0.0 2018年01月 @ngrx/schematics の追加
    6.0.0 2018年05月 AngularのSemantic Versioningに対応

    View full-size slide

  8. NgRx v7紹介
    - @ngrx/store の新機能の紹介
    - @ngrx/entity の新機能の紹介
    - v7でのBreaking Changesの紹介

    View full-size slide

  9. @ngrx/store 新機能
    - Props in Selector (v6.1)

    View full-size slide

  10. // StateのトップレベルのNamespaceを指定するselector
    export const selectFeature = createFeatureSelector(
    'feature'
    );
    // 上記で取得したStateの中からさらに条件を指定して取得
    export const selectCount = createSelector(
    selectFeature,
    (stata) => state.counter
    );
    // 使う時
    const state = store.select(selectCount)
    @ngrx/store とは?
    NgRxの中核であるStoreを提供するモジュール (ReduxのStoreに相当)
    NgRxではコンポーネントがStoreからStateを取得する際には
    selectorという機能が使われる (selectorはSQLのようなもの)

    View full-size slide

  11. // 引数の最後 (ここではid) がpropsとなっている 
    export const selectUserById = createSelector(
    selectUsers,
    (users, id) => users.find(user => user.id === 100)
    );
    Props in Selector
    実際にSelectorを使用する時にpropsを渡して、その結果を使用してStateを取得
    することが可能になる
    // 6.0: 取得した結果から抽出する必要があった
    store.select(selectUsers).pipe(
    map(users => users.find(user => user.id === 100))
    );
    // 6.1: selector側で処理できるようになった
    store.select(selectUserById(100));

    View full-size slide

  12. @ngrx/entity 新機能
    - updateMany by predicate
    - removeMany by predicate

    View full-size slide

  13. function reducer(state = initialState, action: Actions): State {
    switch (action.type) {
    case ActionTypes.ADD_USER: {
    return adapter.addOne(action.payload.user, state);
    }
    case ActionTypes.ADD_USERS: {
    return adapter.addMany(action.payload.users, state);
    }
    case ActionTypes.UPDATE_USER: {
    return adapter.updateOne(action.payload.user, state);
    }
    case ActionTypes.UPDATE_USERS: {
    return adapter.updateMany(action.payload.users, state);
    }
    case ActionTypes.DELETE_USER: {
    return adapter.removeOne(action.payload.id, state);
    }
    case ActionTypes.DELETE_USERS: {
    return adapter.removeMany(action.payload.ids, state);
    }
    // ...
    }
    }
    @ngrx/entity とは?
    Storeの管理でありがちなEntity操作を提供してくれるモジュール
    基本的なCRUD操作をライブラリで提供してくれる

    View full-size slide

  14. function reducer(state = initialState, action: Actions): State {
    switch (action.type) {
    case ActionTypes.MARK_AS_READ: {
    // 保持するEntity全てに変更を適用
    return adapter.map((data) => {
    return data.isRead === false ? { ...data, isRead: true } : data;
    }, state);
    }
    }
    }
    updateMany by predicate
    保持している全Entityに対してmap関数で指定したアップデートを行う
    下記の例では、未読(isRead === false)のデータを全て既読に変更している
    v7からは指定の条件での一括更新を行うことができる

    View full-size slide

  15. // v7
    function reducer(state = initialState, action: Actions): State {
    switch (action.type) {
    case ActionTypes.DELETE_READ: {
    return adapter.removeMany(data => data.isRead, state);
    }
    }
    }
    removeMany by predicate
    保持している全Entityに対して指定の条件に合致するものを削除する
    下記の例では、既読(isRead === true)のデータを全て削除している
    今まではidの配列で削除しなければならなかった
    // v6以前: 複数削除はIDの配列指定が必要だった
    function reducer(state = initialState, action: Actions): State {
    switch (action.type) {
    case ActionTypes.DELETE_READ: {
    return adapter.removeMany([1, 2, 3], state);
    }
    }
    }

    View full-size slide

  16. v7 Breaking Changes
    - Effects: Actions.ofTypeの削除
    - Store: update-reducersのActionのdispatch回数変更
    - RouterStore: デフォルトstate-key名の変更
    - RouterStore: Navigation系のActionの変更

    View full-size slide

  17. // Error
    @Effect()
    effect$ = this.actions$
    .ofType(UserActions.LOGIN)
    .pipe(map(() => new AnotherAction()));
    // OK
    @Effect()
    effect$ = this.actions$.pipe(
    ofType(UserActions.LOGIN),
    map(() => new AnotherAction()),
    );
    Effects: Actions.ofTypeの削除
    非推奨になっていたActions classのstaticメソッドが削除される予定
    これからはRxJSのOperaterとしてのofTypeを使う

    View full-size slide

  18. // v6: 取付/取外した数の分のActionが発行されていた
    {type: '@ngrx/store/update-reducers', feature: 'feat1'}
    {type: '@ngrx/store/update-reducers', feature: 'feat2'}
    // v7: Actionは1回になり、配列で渡るようになった
    {type: '@ngrx/store/update-reducers', features: ['feat1', 'feat2']}
    Store: update-reducersのActionのdispatch回数変更
    Storeに対してReducerを取付/取外したときに発行されるActionの仕様変更
    (普通は使わないが、store-devtoolsの実装に影響を与えたりしている)

    View full-size slide

  19. // v6
    {
    routerReducer: RouterReducerState
    }
    // v7
    {
    router: RouterReducerState
    }
    RouterStore: デフォルトstate-key名の変更
    RouterStoreModuleがRouterのデータをStateオブジェクトに追加する時の
    key名が変更された ("routerReducer" から "router")
    // おまけ: state-keyは自分で指定することもできる。v7からはselectorも使えるようになった
    StoreRouterConnectingModule.forRoot({
    stateKey: 'my-custom-key',
    })
    StoreRouterConnectingModule.forRoot({
    stateKey: (state) => state['my-key'],
    })

    View full-size slide

  20. RouterStore: Navigation系のActionの変更
    Routerのイベントによって発行されるActionが新規で2つ追加されて、
    発行されるタイミングなどが少し変わった (追加前は3種類、追加後は5種類)
    この変更によってより柔軟にRouterを扱えるようになった
    ROUTER_NAVIGATION:
    ROUTER_CANCEL:
    ROUTER_ERROR:
    v6
    RoutesRecognized
    NavigationCancel
    NavigationError
    ROUTER_REQUEST:
    ROUTER_NAVIGATION:
    ROUTER_NAVIGATED:
    ROUTER_CANCEL:
    ROUTER_ERROR:
    v7
    NavigationStart
    RoutesRecognized
    NavigationEnd
    NavigationCancel
    NavigationError

    View full-size slide

  21. その他 NgRx 最近のトピック
    - リポジトリ構成の変更
    - Good Action Hygiene の適用

    View full-size slide

  22. - ngrx/platform
    - modules/
    - effects/
    - entity/
    - router-store/
    - schematics/
    - schematics-core/
    - store/
    - store-devtools/
    - example-app/
    - example-app-e2e/
    ngrx/platform リポジトリ構成の変更
    ngrx.ioの導入に伴い、projectsというディレクトリが追加されて、example-app
    などはそちらで管理されるようになった
    - ngrx/platform
    - modules/
    - effects/
    - entity/
    - router-store/
    - schematics/
    - schematics-core/
    - store/
    - store-devtools/
    - projects/
    - example-app/
    - example-app-e2e/
    - ngrx.io/

    View full-size slide

  23. Good Action Hygiene の適用
    example-app のプロジェクトがGood Action Hygiene対応された。
    Good Action Hygieneとは?
    ng-conf2018でMike Ryanさんが発表したアクションのカテゴライズと命名方法。これを
    適用することで、アクションはより的確にアプリケーションの仕様を表現することができ
    る。

    View full-size slide

  24. https://www.youtube.com/watch?v=JmnsEvoy-gY

    View full-size slide

  25. https://www.youtube.com/watch?v=JmnsEvoy-gY

    View full-size slide

  26. ngrx.io
    - angular.ioと同じ設計のドキュメントサイト
    - masterにマージ済み、近日リリース予定

    View full-size slide

  27. おわりに
    - Good Action Hygeineなどのベストプラクティスも出てきて、
    NgRx界隈は徐々に盛り上がっている
    - 本家Angular、Materialに比べると開発にそれほど勢いはな
    いが、着実に良くなっていっている
    - v7ではさらにユーザ数が増えることを期待

    View full-size slide