7

Normalizr は、エンティティの構造化された JSON リポジトリを作成するのに優れています。

posts正規化されたデータなどのリストを表示するケースが多くあります。postsAPI 応答がリストされている場所は、いくつかの重要なフィールドに限定されています。

これらのいずれかを表示するケースもありpostsますが、すべてのフィールドを含む完全な JSON エンティティを API から取得する必要があります。

これにどのように対処するのが最善ですか?

個別のレデューサー、サンク/サガ、セレクター、アクション?

Bpostは、API から取得した拡張バージョンをレデューサーに挿入するだけです。以前のセレクターなどを再利用していますか?

4

2 に答える 2

8

アプリの状態をデータベースと考えてください。この状態形状を使用することをお勧めします。

{
  entities: {
    // List of normalized posts without any nesting. No matter whether they have all fields or not.
    posts: {
      '1': {
        id: '1',
        title: 'Post 1',
      },
      '2': {
        id: '2',
        title: 'Post 2',
      }
    },
  },
  // Ids of posts, which need to displayed.
  posts: ['1', '2'],
  // Id of full post.
  post: '2',
}

まず、normalizrスキーマを作成します。

// schemas.js
import { Schema, arrayOf } from 'normalizr';

const POST = new Schema('post');
const POST_ARRAY = arrayOf(POST);

成功応答の後、応答データを正規化し、アクションをディスパッチします。

// actions.js/sagas.js
function handlePostsResponse(body) {
  dispatch({
    type: 'FETCH_POSTS',
    payload: normalize(body.result, POST_ARRAY),
  });
}

function handleFullPostResponse(body) {
  dispatch({
    type: 'FETCH_FULL_POST',
    payload: normalize(body.result, POST),
  });
}

entitiesレデューサーでは、すべてのアクションをリッスンしentities、ペイロードにキーがある場合は、このエンティティをアプリの状態に追加するレデューサーを作成する必要があります。

// reducers.js
import merge from 'lodash/merge';

function entities(state = {}, action) {
  const payload = action.payload;

  if (payload && payload.entities) {
    return merge({}, state, payload.entities);
  }

  return state;
}

FETCH_BOARDSまた、処理とFETCH_FULL_BOARDアクションに対応するレデューサーを作成する必要があります。

// Posts reducer will be storing only posts ids.
function posts(state = [], action) {
  switch (action.type) {
    case 'FETCH_POSTS':
      // Post id is stored in `result` variable of normalizr output.
      return [...state, action.payload.result];
    default:
      return state;
  }
}

// Post reducer will be storing current post id.
// Further, you can replace `state` variable by object and store `isFetching` and other variables.
function post(state = null, action) {
  switch (action.type) {
    case 'FETCH_FULL_POST':
      return action.payload.id;
    default:
      return state;
  }
}
于 2016-07-01T14:58:38.297 に答える
3

私はあなたの 2 つの選択肢の両方に同意し、同じ結論に達したでしょう。しかし、それらを詳しく見て、それぞれの利点を見てみましょう。

(B)ポスト エンティティ (プレビューと完全な表現) をレデューサーの 1 つのエンティティとしてマージできますが、配列 (プレビューと完全な表現) を追跡しresultます。これは、API 要求の後に正規化された正規化データから取得します。 . 投稿の完全な表現がすでにある場合は、後で簡単に区別できます。サブステートは次のようになります。

const postState = {
  // merged results from PREVIEW api
  previews: [1, 2, 3],

  // merged results from FULL api
  full: [2],

  // all merged entities
  entities: {
    1: {
      title: 'foo1'
    },
    2: {
      title: 'foo2',
      body: 'bar',
    },
    3: {
      title: 'foo3'
    }
  }
}; 

(A)エンティティを区別するために、表現ごとに 1 つずつ、2 つのレデューサー + アクションがあります。PREVIEW または FULL 投稿 API リクエストに応じて、1 つの明示的なアクションを介してレデューサーの 1 つを提供します。サブステートは次のようになります。

const previewPostState = {
  // merged results from PREVIEW api
  result: [1, 2, 3],

  // all preview entities
  entities: {
    1: {
      title: 'foo1'
    },
    2: {
      title: 'foo2',
    },
    3: {
      title: 'foo3'
    }
  }
}; 

const fullPostState = {
  // merged results from FULL api
  result: [2],

  // all full entities
  entities: {
    2: {
      title: 'foo2',
      body: 'bar'
    }
  }
}; 

非常に高いレベルの観点から、重複した情報を保存しなければならないことがすでにわかります。の post エンティティはid: 2、タイトル プロパティを使用して 2 回保存さpreviewPostStatefullPostStateます。グローバル状態で title プロパティを変更したい場合は、2 つの場所で行う必要があります。Redux の単一の信頼できる情報源に違反することになります。それが私が選択肢(B)を使用する理由です: 投稿エンティティの場所は 1 つありますが、結果の配列によってそれらの表現を明確に区別できます。

于 2016-08-06T10:39:47.440 に答える