7

既存のアプリを Flux に移植していますが、1 つのトピックについて少し混乱しています。2 レベルまたは 3 レベルのネストされたオブジェクトを返す API エンドポイントがいくつかあるとします。

たとえば、GET /articlesスキーマの JSON 応答を返す場合があります

articles: article*

article: {
  author: user,
  likers: user*
  primary_collection: collection?
  collections: collection*
}

collection: {
  curator: user
}

ご覧のとおり、さまざまなレベルのネストにあらゆる種類のユーザーがいます。

  • articles[i].author
  • articles[i].likers[i]
  • articles[i].primaryCollection.curator
  • articles[i].collections[i].curator

記事がフェッチされるたびに新しいデータで更新したい場合はUserStore、記事の API 応答でネストされたすべてのエンティティをチェックする巨大なメソッドを作成する必要があります。さらに、スキーマが異なる他の A​​PI エンドポイントもあり、記事がユーザー内に埋め込まれている場合があるため (例: GET /user/published)、多くの重複が発生します。

Flux ストアがすべての API 応答からネストされたエンティティを抽出するためのよりクリーンな方法はありますか?

4

1 に答える 1

7

Jing Chen (Flux の作成者およびエバンジェリストの 1 人)が提案したアプローチは、ストアに到達する前に API 応答をフラットにすることでした。私はそれを行う小さなライブラリを書きました:それは正規化します

[{
  id: 1,
  title: 'Some Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}, {
  id: 2,
  title: 'Other Article',
  author: {
    id: 1,
    name: 'Dan'
  }
}]

{
  result: [1, 2],
  entities: {
    articles: {
      1: {
        id: 1,
        title: 'Some Article',
        author: 1
      },
      2: {
        id: 2,
        title: 'Other Article',
        author: 1
      }
    },
    users: {
      1: {
        id: 1,
        name: 'Dan'
      }
    }
  }
}

(重複がなく、構造がフラットであることに注意してください。)

Normalizrでは次のことができます。

  • エンティティを他のエンティティ、オブジェクト、および配列内にネストする
  • エンティティ スキーマを組み合わせて、あらゆる種類の API 応答を表現する
  • 同じ ID を持つエンティティを自動的にマージ (異なる場合は警告あり)
  • カスタム ID 属性 (スラッグなど) を使用する

これを使用するには、エンティティとネスト ルールを定義し、それらを使用して JSON を変換する必要があります。

var normalizr = require('normalizr'),
    normalize = normalizr.normalize,
    Schema = normalizr.Schema,
    arrayOf = normalizr.arrayOf;

// First, define a schema:

var article = new Schema('articles'),
    user = new Schema('users'),
    collection = new Schema('collections');

// Define nesting rules:

article.define({
  author: user,
  collections: arrayOf(collection)
});

collection.define({
  curator: user
});


// Usage:

// Normalize articles
var articlesJSON = getArticleArray(),
    normalized = normalize(articlesJSON, arrayOf(article));

// Normalize users
var usersJSON = getUsersArray(),
    normalized = normalize(usersJSON, arrayOf(user));

// Normalize single article
var articleJSON = getArticle(),
    normalized = normalize(articleJSON, article);

これにより、XHR レスポンスを Flux Dispatcher に渡す前に正規化できます。ストアは、対応する辞書から自身を更新するだけで済みます。

// UserStore

UserStore.dispatchToken = AppDispatcher.register(function (payload) {
  var action = payload.action;

  switch (action.type) {
  // you can add any normalized API here since that contains users:
  case ActionTypes.RECEIVE_ARTICLES:
  case ActionTypes.RECEIVE_USERS:

    // Users will always be gathered in action.entities.users
    mergeInto(_users, action.entities.users);
    UserStore.emitChange();
    break;
  }
});


// ArticleStore

AppDispatcher.register(function (payload) {
  var action = payload.action;

  switch (action.type) {
  // you can add any normalized API here since that contains articles:
  case ActionTypes.RECEIVE_ARTICLES:

    // Wait for UserStore to digest users
    AppDispatcher.waitFor([UserStore.dispatchToken]);

    // Articles will always be gathered in action.entities.articles
    mergeInto(_articles, action.entities.articles);
    ArticleStore.emitChange();
    break;
  }
});
于 2014-08-20T15:50:19.173 に答える