高度なNGRX:再利用可能な機能ストアの構築


角度のアプリケーションがスケールと複雑さで成長するので、しばしば、多くの可動部分を単純化するのを助ける州管理の必要性です.しばしば起こることは、多くの機能状態を管理することに関係するボイラープレートの量の増加および記憶装置である.
ストアサイズの増加はしばしば、不良部品設計のように繰り返しパターンにつながる.しかし、状態がうまく書かれている場合、アプリケーションは、一般的なパターン-再利用可能な機能ストアを利用することができます-我々は、このboilerplate頭痛の多くを排除しようとします.
以下は、いくつかのストアを適切に統合するパターンを作成し、再利用可能なストアと同様の機能を一貫して得るパターンを提案します.

締約国管理パターンを使用する場合
私たちが統合することにあまりに深くなる前に、我々は最初に止まって、評価しなければなりません.

なぜ第一に統合するのか?
  • は、機能設計の繰り返しパターンを減らします.
  • は、類似した特徴の保守性を増やしました.
  • クイック反復.
  • エッジケースに必要に応じて拡張できる、より良い共有抽象化レイヤ.
  • 類似または拡張可能なUIまたはデータストア.

  • いつ、あなたは固守すると思いますか?
    質問に答えるのは難しいが、1つは本当に良い先見性、アプリケーションの機能がどのように動作するかのロードマップ、または全体的なデザインに近いそれらをもたらすためにいくつかの反復を必要とする可能性のある既存の機能のセットによって満足している.
    これが両方のアプローチのために意味することは、機能が最初にもう一つと同様に設計されることができるか、後でそれを乾くようにするためにもう一つと同様に機能するようにされるということです.

    ストアパターンをより詳しく見る
    私たちの努力の方向と理由があるので、写真のウェブサイト- unsplashの模擬版を使用してパターンを見てみましょう-データストアを構築する.
    このようにいくつかの州があります.
    export interface WallpapersState {
        photos: Photo[];
        isLoading: boolean;
    }
    
    export interface PeopleState extends Photo {
        photos: Photo[];
        isLoading: boolean;
    }
    ...
    // rest of states for remaining photo types
    
    幸いにも、我々の写真資産は、非常に類似したパターンに続きます.それは単純な状態で写真を含むように、この状態は簡単です.しかし、以下のような状態にすることができます.
    export interface PhotoState {
      photos: Photo[];
      isLoaded: boolean;
      isLoading: boolean;
    }
    
    export interface PhotoTypeState {
      [assetType: string]: PhotoState;
    }
    
    そして、コードのその単純なビットで、我々は1つの店に写真タイプにつきデータ記憶装置を再利用する可能性を開けました!
    例えば、Unsplashのようなウェブサイトでは、ナビゲーションの写真タイプによるフィルタリングのような写真を取得したり、レゾルバでフォトタイプのプリフェッチチャンクを表示するためにいくつかの戦略を使用することができます.それぞれの写真の種類は、個々のストアとして動作する場合想像してみませんか?それは、維持する多くの店です!

    新しい状態と減速機の構築
    この新しい機能ストアが構築されるように、型としてインデックス付きインターフェイスを使用し始めるときにタイピングがトリッキーになることを心に留めておいてください.

    落とし穴
    TypeScriptは、インデックスプロパティに割り当てられた最初の型に従うプロパティを追加するだけであると仮定します.この場合はPhoto[]である.
    例えば、次のように動作します.
    export interface PhotoTypeState {
      [assetType: string]: PhotoState;
    }
    
    しかし、これはPhotoTypeselectedPhotoTypeがタイプで重なっていないからです.
    export interface PhotoTypeState {
      selectedPhotoType: PhotoType; // for selecting the right photo store
      [assetType: string]: PhotoState;
    }
    
    これを解決するには、次のような交差点型を使用できます.
    export interface PhotoTypesState {
      [photoType: string]: PhotoState;
    }
    
    export type State = PhotoTypesState & {
      selectedPhotoType: PhotoType;
    };
    

    再利用可能な状態の一部の定義
    私たちの店では柔軟性のいくつかの量が欲しいが、我々は新しい店をどのような機能は、パターンで同様に維持するつもりです教えてください.我々がこれをする1つの方法は、機能の辞書を作成することです.フォト型の初期状態を構築するには次のようになります.
    // Dictionary referencing the phtoto types as features
    export enum PhotoType {
      Promos = "Promos",
      Wallpapers = "Wallpapers",
      People = "People",
      Nature = "Nature",
      Architecture = "Architecture",
      Misc = "Misc",
    }
    
    // Initial state for each photo type
    export const INITIAL_PHOTO_TYPE_STATES: PhotoTypeState = Object.keys(
      PhotoType
    ).reduce((acc, val) => {
      acc[PhotoType[val]] = [];
      return acc;
    }, {});
    
    還元器の初期状態
    /**
     * Initialize the default photo type.
     *
     * NOTE: we have to assign an initial value in this
     * example's load strategy so our selector doesn't read
     * the state as `undefined`.
     *
     * Because we used an indexed type, we would have to
     * force type properties to `any` to avoid type conflicts.
     *
     * To get around an initial value and use `null`, change
     * your load to one that makes sense for you app.
     */
    export const INITIAL_PHOTOS_STATE: PhotosState = {
      selectedPhotoType: PhotoType.Promos as any,
      ...INITIAL_PHOTO_TYPE_STATES,
    };
    

    再利用可能なストアパターンのもう一つの勝利
    多分、あなたはすでに気づいたでしょう、しかし、個々の州の各々が実体を使用するならば、どうですか?私たちは自分自身を助けることができ、アダプタのメソッドとセレクタをPhotoTypeにさらされると、私たちのdevの時間をもう少し高速化しました.ここでの我々の最大の勝利は、我々がまだ国家のこれらの一見入れ子状態でさえNGRX実体を使うことができるという事実から来ます.以下のように変更されます.
        export interface PhotoEntitiesState extends EntityState<PhotoState> {
            // additional entity state properties
        }
    
        export interface PhotoTypeEntitiesState {
            [photoType: string]: PhotoEntitiesState;
        }
        ...
        const adapter: EntityAdapter<PhotoState> = createEntityAdapter<PhotoState>({
            // additional entity state properties
        });
    
    状態スライスを初期状態にします.
    export const INITIAL_PHOTO_TYPE_STATES: PhotoTypeState = Object.keys(
      PhotoType
    ).reduce((acc, val) => {
      acc[PhotoType[val]] = adapter.getInitialState({});
      return acc;
    }, {});
    

    減速器と選択器を結びつける
    今、我々は国家が正確に定義されている.我々は、selectedPhotoTypeプロパティを使用して、単一のストアの選択スライスにアクセスできます.
    export const photosReducer = createReducer(
      INITIAL_PHOTOS_STATE,
      on(PhotoActions.loadPhotoSuccess, (state, { photos }) => ({
        ...state,
        [state.selectedPhotoType]: {
          ...state[state.selectedPhotoType],
          photos,
        },
      }))
    );
    
    とセレクタの場合:
    export const photosState = createFeatureSelector("photos");
    
    export const selectActivePhotoTypeState = createSelector(
      photosState,
      (state) => state[state.selectedPhotoType]
    );
    
    export const selectAllPhotos = createSelector(
      selectActivePhotoTypeState,
      (state) => state.photos
    );
    
    再び、エンティティアダプタとエンティティメソッドとセレクタを使用できます.Full Code Example Here .

    結論
    NGRXの状態管理店で働くとき、同じ店の形でいくつかのデータ源に影響を与えるボイラー板と変化を維持することは混乱してはいけません.開発者として、我々は十分に抽象的な、まだまだ私たちは正確にどのようにアプリケーションが機能を理解するのに役立つ将来の戦略を考えたい.
    再利用可能なストア戦略を活用することによって、我々は同様の機能、抽象化のレベルと同様の機能の間の整合性を得る、能力のエッジケース、およびより簡単なメンテナンスのために拡張する.
    このドットラボは、企業のデジタル変換の努力を実現支援に焦点を当てた現代のWebコンサルティングです.専門家の建築指導、訓練、または反応、角度、Vue、Webコンポーネント、Graphql、ノード、バゼル、またはポリマー、コンサルテーションthisdotlabs.comをご覧ください.
    このドットメディアは、すべての包括的で教育的なウェブを作成することに集中します.我々は最新のイベント、ポッドキャスト、および無料のコンテンツを介して近代的なWebの進歩と最新の状態に保つ.学ぶには、thisdot.coをご覧ください.