13

私はfluxを使い始めたばかりで(今のところreduxを使用)、関係をどのように処理する必要があるのか​​ 疑問に思っています。
例として、カードを含む列を持つボードを持つ Trello を使用できます。

1 つのアプローチは、ボード用に 1 つのストア/リデューサーを用意し、そこにすべてのデータを格納することですが、これは列とカードのすべてのアクションも含める必要があるため、非常に太いストアを意味します。

私が見た別のアプローチは、ネストされたリソースをたとえばBoardStore、ColumnStore、CardStoreに分離し、それらのIDを参照として使用することです。

少し混乱している例を次に示します。すべてのデータを含むカードを作成するようにサーバーに要求する addCard というアクション クリエーターを使用できます。楽観的な更新を行っている場合は、以前にストアの 1 つでカード オブジェクトを作成したことになりますが、リクエストが返されるまでその ID を知ることはできません。

要するに:

  • addCardの発火
  • addCard はリクエストを行いますが、その間にタイプ ADD_CARD_TEMP のアクションを返します
  • リクエストを取得し、ストア/リデューサーが ID を変更するタイプ ADD_CARD のアクションを返します。

この場合に対処するための推奨される方法はありますか? ネストされたストア/レデューサーは私には少しばかげているように見えますが、それ以外の場合は非常に複雑なストアになってしまうため、実際には妥協のように見えます.

4

1 に答える 1

8

はい、リレーショナル データベースのように複数のストアで ID を使用するのが正しい方法です。

あなたの例では、楽観的に新しいカードを特定の列に配置したいとしましょう。また、カードは 1 つの列 (1 つの列から多くのカード) にのみ配置できます。

CardStore のカードは次のようになります。

_cards: {
  'CARD_1': {
    id: 'CARD_1',
    columnID: 'COLUMN_3',
    title: 'Go to sleep',
    text: 'Be healthy and go to sleep on time.',
  },
  'CARD_2': {
    id: 'CARD_2',
    columnID: 'COLUMN_3',
    title: 'Eat green vegetables',
    text: 'They taste better with onions.',
  },
}

ID でカードを参照できることに注意してください。また、オブジェクト内で ID を取得することもできます。これによりgetCard(id)、ビューレイヤー内の特定のカードの ID を取得したり、取得したりすることができます。したがってdeleteCard(id)、ビュー内の ID を知っているため、アクションに応答して呼び出されるメソッドを持つことができます。

カード ストア内にはgetCardsByColumn(columnID)、カード オブジェクトの単純なマップである があり、これにより、列の内容をレンダリングするために使用できるカードの配列が生成されます。


楽観的な更新の仕組みと、ID の使用がそれに与える影響について:

XHR 応答を処理する同じクロージャー内で確立されたクライアント側 ID を使用し、応答が成功として戻ってきたときにクライアント側 ID をクリアするか、代わりにエラーでロールバックすることができます。クロージャーにより、応答が返されるまでクライアント側の ID を保持できます。

多くの人が、クライアント側の ID と要求/応答を保持するクロージャーに関連するすべてのメソッドを含む WebAPIUtils モジュールを作成します。アクションの作成者 (またはストア) は、この WebAPIUtils モジュールを呼び出して、要求を開始できます。

したがって、次の 3 つのアクションがあります。

  1. リクエストを開始する
  2. 成功を処理する
  3. 応答を処理する

リクエストを開始するアクションに応答して、ストアはクライアント側の ID を受け取り、レコードを作成します。

成功/エラーに応答して、ストアは再びクライアント側 ID を受け取り、レコードを実際の ID を持つ確認済みレコードに変更するか、代わりにレコードをロールバックします。また、ユーザーに再試行させるなど、そのエラーに関する優れた UX を作成することもできます。

コード例:

// Within MyAppActions
cardAdded: function(columnID, title, text) {
  var clientID = this.createUUID();
  MyDispatcher.dispatch({
    type: MyAppActions.types.CARD_ADDED,
    id: clientID,
    columnID: columnID,
    title: title,
    text: text,
  });
  WebAPIUtils.getRequestFunction(clientID, "http://example.com", {
    columnID: columnID,
    title: title,
    text: text,
  })(); 
},

// Within WebAPIUtils
getRequestFunction: function(clientID, uri, data) {
  var xhrOptions = {
    uri: uri,
    data: data,
    success: function(response) {
      MyAppActions.requestSucceeded(clientID, response);
    },
    error: function(error) {
      MyAppActions.requestErrored(clientID, error);
    },
  };
  return function() {
    post(xhrOptions);
  };
},

// Within CardStore
switch (action.type) {

  case MyAppActions.types.CARD_ADDED:
    this._cards[action.id] = {
      id: action.id,
      title: action.title,
      text: action.text,
      columnID: action.columnID,
    });
    this._emitChange();
    break;

  case MyAppActions.types.REQUEST_SUCCEEDED:
    var tempCard = this._cards[action.clientID];
    this._cards[action.id] = {
      id: action.id,
      columnID: tempCard.columnID,
      title: tempCard.title,
      text: tempCard.text,
    });
    delete this._cards[action.clientID];
    break;

  case MyAppActions.types.REQUEST_ERRORED:
    // ...
}

名前の詳細とこの実装の詳細にあまり注意を払わないでください (タイプミスやその他のエラーがある可能性があります)。これは、パターンを説明するためのコード例です。

于 2015-07-28T04:27:04.117 に答える