web-dev-qa-db-ja.com

オブジェクト内のネストされた配列を処理するngrx

私はreduxパターンを学び、angular 2。でngrxを使用しています。次の形のサンプルブログサイトを作成しています。

export interface BlogContent {
  id: string;
  header: string;
  tags: string[];
  title: string;
  actualContent: ActualContent[];
}

私のレデューサーとアクションは次のとおりです。

import { ActionReducer, Action } from '@ngrx/store';
import * as _ from 'lodash';
export interface ActualContent {
  id: string;
  type: string;
  data: string;
}

export interface BlogContent {
  id: string;
  header: string;
  tags: string[];
  title: string;
  actualContent: ActualContent[];
}

export const initialState: BlogContent = {
  id: '',
  header: '',
  tags: [],
  title: '',
  actualContent: [],
};

export const ADD_OPERATION = 'ADD_OPERATION';
export const REMOVE_OPERATION = 'REMOVE_OPERATION';
export const RESET_OPERATION = 'RESET_OPERATION';
export const ADD_IMAGE_ID = 'ADD_IMAGE_ID';
export const ADD_FULL_BLOG = 'ADD_FULL_BLOG';
export const ADD_BLOG_CONTENT_OPERATION = 'ADD_BLOG_CONTENT_OPERATION';
export const ADD_BLOG_TAG_OPERATION = 'ADD_BLOG_TAG_OPERATION';

export const blogContent: ActionReducer<BlogContent> = (state: BlogContent= initialState, action: Action ) => {
    switch (action.type) {
      case  ADD_OPERATION :
        return Object.assign({}, state, action.payload );
      case  ADD_BLOG_CONTENT_OPERATION :
        return Object.assign({}, state, { actualContent: [...state.actualContent, action.payload]});
        case  ADD_BLOG_TAG_OPERATION :
        return Object.assign({}, state, { tags: [...state.tags, action.payload]});
      case REMOVE_OPERATION :
        return Object.assign({}, state, { actualContent: state.actualContent.filter((blog) => blog.id !== action.payload.id) });
      case ADD_IMAGE_ID : {
        let index = _.findIndex(state.actualContent, {id: action.payload.id});
        console.log(index);
        if ( index >= 0 ) {
          return  Object.assign({}, state, {
            actualContent :  [
              ...state.actualContent.slice(0, index),
              action.payload,
              ...state.actualContent.slice(index + 1)
            ]
          });
        }
        return state;
      }
      default :
        return state;
    }
};

これは正常に機能していますが、それが正しいアプローチであるかどうか、または実際のコンテンツを独自のレデューサーとアクションに分離してからそれらをマージする必要があるかどうかはわかりません。この投稿がここに属していない場合は申し訳ありません。この投稿をどこに置くべきかを教えていただければ、ここから削除します。前もって感謝します。

P.S.私はいくつかの調査を行いましたが、参照できるように複雑なネストされたオブジェクトを持つ記事を見つけることができませんでした。私を助けることができるngrxまたは関連トピックの有用なブログリンクを追加してください。

15
fastAsTortoise

ネストされた構造を持つ代わりに

export interface BlogContent {
  id: string;
  header: string;
  tags: string[];
  title: string;
  actualContent: ActualContent[]; <------ NESTED
}

正規化された状態になっているはずです。

たとえば、ここでは次のようなものが必要です。

// this should be into your store
export interface BlogContents {
  byId: { [key: string]: BlogContent };
  allIds: string[];
}

// this is made to type the objects you'll find in the byId
export interface BlogContent {
  id: string;
  // ...
  actualContentIds: string[];
}

// ----------------------------------------------------------

// this should be into your store
export interface ActualContents {
  byId: { [key: string]: ActualContent };
  allIds: string[];
}

export interface ActualContent {
  id: string;
  // ...
}

したがって、ストアにデータを入力しようとすると、次のようになります。

const blogContentsState: BlogContents = {
  byId: {
    blogContentId0: {
      id: 'idBlogContent0',
      // ...
      actualContentIds: ['actualContentId0', 'actualContentId1', 'actualContentId2']
    }
  },
  allIds: ['blogContentId0']
};

const actualContentState: ActualContents = {
  byId: {
    actualContentId0: {
      id: 'actualContentId0',
      // ...
    },
    actualContentId1: {
      id: 'actualContentId1',
      // ...
    },
    actualContentId2: {
      id: 'actualContentId2',
      // ...
    }
  },
  allIds: ['actualContentId0', 'actualContentId1', 'actualContentId2']
};

ロジックまたはビュー(Angularなど)では、配列を反復処理できるようにネストされた構造が必要であるため、IDの文字列配列を反復処理する必要はありません。代わりにactualContent: ActualContent[];

そのために、selectorを作成します。ストアが変更されるたびに、セレクターが起動し、生データの新しい「ビュー」を生成します。

// assuming that you can blogContentsState and actualContentsState from your store
const getBlogContents = (blogContentsState, actualContentsState) =>
  blogContentsState
    .allIds
    .map(blogContentId => ({
      ...blogContentsState.byId[blogContentId],

      actualContent: blogContentsState
        .byId[blogContentId]
        .actualContentIds
        .map(actualContentId => actualContentsState.byId[actualContentId])
    }));

最初に処理するのは大変なことだと思います。 セレクターと正規化された状態に関する公式ドキュメント をお読みください。

Ngrxを学習しているときに、Pizza-Syncと呼ばれる私が作成した小さなプロジェクトを調べてみることをお勧めします。 コードソースはGithubにあります 。それは私がデモのためにそのようなことをしたプロジェクトです:)。 (ストアの状態を確認するには、 ReduxDevToolsアプリ も必ずインストールする必要があります)。

興味があれば、Pizza-Syncを使用したReduxのみに小さなビデオを作成しました: https://youtu.be/I28m9lwp15Y

15
maxime1992