2015-07-26 1 views
11

Je commence tout juste à utiliser flux (avec redux pour l'instant) et je me demande comment les relations sont censées être gérées.
Pour un exemple, nous pouvons utiliser Trello qui a des cartes avec des colonnes qui contient des cartes. Une approche serait d'avoir un magasin/réducteur pour les planches et d'y avoir toutes les données, mais cela signifie des magasins très gros car ils devraient aussi contenir toutes les actions pour les colonnes et les cartes.Comment gérer les relations un-à-plusieurs dans les magasins Flux

Une autre approche que j'ai vu est de séparer les ressources imbriquées dans par exemple BoardStore, ColumnStore et CardStore et d'utiliser leurs ids comme référence.

Voici un exemple où je suis un peu confus: vous pourriez avoir un créateur d'action appelé addCard qui fait une requête au serveur pour créer une carte avec toutes les données. Si vous faites une mise à jour optimiste, vous auriez créé un objet carte dans l'un de vos magasins avant, mais vous ne pouvez pas connaître l'identifiant qu'il aura jusqu'à ce que vous récupériez la demande.

Donc en bref:

  • mise à feu addCard
  • addCard ne demande, en attendant vous retournez une action de type ADD_CARD_TEMP
  • vous obtenez la demande et le retour d'une action de type ADD_CARD où le magasin/réducteur modifie l'identifiant.

Existe-t-il une méthode recommandée pour traiter ce cas? Les magasins/réducteurs imbriqués me paraissent un peu idiots, mais sinon vous vous retrouvez avec des magasins très complexes, cela ressemble vraiment à un compromis.

Répondre

7

Oui, l'utilisation d'identifiants dans plusieurs magasins, à la manière d'une base de données relationnelle, est la bonne façon de procéder. Dans votre exemple, supposons que vous souhaitiez mettre une nouvelle carte dans une colonne donnée de manière optimiste, et qu'une carte ne puisse contenir qu'une seule colonne (d'une colonne à plusieurs cartes).

Les cartes dans votre CardStore pourrait ressembler à ceci:

_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.', 
    }, 
} 

Notez que je peux faire référence à une carte par l'identifiant, et je peux aussi récupérer l'identifiant dans l'objet. Cela me permet d'avoir des méthodes comme getCard(id) et également être en mesure de récupérer l'ID d'une carte particulière dans la couche de vue. Ainsi, je peux avoir une méthode deleteCard(id) qui est appelée en réponse à une action, car je connais l'identifiant dans la vue.

Dans le magasin de cartes, vous auriez getCardsByColumn(columnID), qui serait une simple carte sur les objets de la carte, et cela produirait un tableau de cartes que vous pourriez utiliser pour rendre le contenu de la colonne.


En ce qui concerne la mécanique des mises à jour optimistes, et comment l'utilisation des ids l'affecte:

Vous pouvez utiliser un id côté client qui est établie dans la même fermeture qui traitera la réponse XHR, et effacez l'identificateur côté client lorsque la réponse est considérée comme réussie ou à la place, annulez l'erreur. La fermeture vous permet de conserver l'identifiant côté client jusqu'à ce que la réponse revienne.

Beaucoup de gens vont créer un module WebAPIUtils qui contiendra toutes les méthodes liées à la fermeture en conservant l'identifiant côté client et la demande/réponse. Le créateur de l'action (ou le magasin) peut appeler ce module WebAPIUtils pour lancer la requête.

Vous avez donc trois actions:

  1. initié demande
  2. poignée succès
  3. réponse poignée

En réponse à l'action qui déclenche la demande, votre magasin reçoit le client- côté id et crée l'enregistrement.

En cas de réussite/d'erreur, votre magasin reçoit à nouveau l'ID côté client et modifie l'enregistrement pour qu'il soit un enregistrement confirmé avec un ID réel ou annule l'enregistrement. Vous voudriez également créer un bon UX autour de cette erreur, comme laisser votre utilisateur essayer encore.

code Exemple:

// 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: 
    // ... 
} 

S'il vous plaît ne soyez pas trop pris sur les détails des noms et les détails de cette mise en œuvre (il y a probablement des fautes de frappe ou d'autres erreurs). Ceci est juste un exemple de code pour expliquer le motif.

+0

Merci pour la réponse. Désolé si je n'étais pas clair mais ma question était plus comment organiser le magasin et j'ai utilisé la mise à jour optimiste comme exemple d'un problème possible de référencer quelque chose par ID. –

+0

oh désolé. J'ai mis à jour ma réponse. J'espère que cela répond à votre question. – fisherwebdev

+0

Je n'étais pas assez clair :) À la vôtre –