2017-10-15 6 views
1

J'ai besoin d'aide pour comprendre ce qu'est une approche générale sur les abonnements et la mise à jour en temps réel. J'ai une application React Native et j'utilise le service Apollo et Graphcool comme backend.Comment approcher les abonnements dans l'application React

Il existe plusieurs scénarios dans lesquels l'utilisateur qui regarde l'application reçoit une notification push indiquant que quelque chose a changé. Naturellement, les données de l'écran doivent également être mises à jour. Les abonnements sont un candidat évident pour ce travail et je l'ai fait fonctionner essentiellement.

J'ai un abonnement comme celui-ci qui fonctionne très bien seul (utilisé pour positionner les avatars du joueur sur google map).

subscription PlayerMap($gameId: ID) { 
    Game(filter: { mutation_in: [CREATED, UPDATED], node: { id: $gameId } }) { 
    node { 
     players { 
     id 
     character { 
      id 
      name 
     } 
     user { 
      id 
      latitude 
      longitude 
     } 
     } 
    } 
    } 
} 

Ensuite, il y a un autre écran d'application exécutant une mutation createPlayer avec refetchQueries d'Apollo (pour simplifier) ​​qui exécute cette requête pour mettre à jour des choses.

query GameCharacters($gameId: ID!) { 
    Game(id: $gameId) { 
    players { 
     id 
     character { 
     id 
     name 
     } 
    } 
    } 
} 

Maintenant, lorsque cela est terminé, la requête d'abonnement (qui est toujours actif sur un autre écran) obtient également mis à jour, mais pour une raison tout noeud Game manque dans l'objet data.

Pour la gestion des abonnements, j'ai un composant comme celui-ci. Je peux ensuite l'utiliser simplement comme ceci avec un motif de rendu de rendu.

const OrgMapScreen = ({ gameId, data: initialData }: Props) => (
    <Subscriber 
    data={initialData} 
    query={OrgMapSubscription} 
    variables={{ gameId }} 
    shouldResubscribe={(nextData, prevData) => nextData.Game !== prevData.Game} 
    > 
    {({ Game }) => { 
     const markers = Game.players.map(makePlayerMarker) 
     return <MapScreen mapProps={{ markers }} /> 
    }} 
    </Subscriber> 
) 

Je suis plutôt confus pourquoi cela se produit-il. Y at-il une façon recommandée de gérer des choses comme ça? Peut-être au lieu de refetchQueries je devrais mettre en place un autre abonnement pour GameCharacters aussi?

Répondre

2

Si je devais deviner (pas un expert Apollo), je suppose que cela a à voir avec la mauvaise entrée document dans votre subscribeToMore (il semble que vous utilisez la requête et non l'abonnement en tant que paramètre?) ou un updateQuery manquant dans subscribeToMore, qui renvoie les données mises à jour.

Dans notre cas, nous avons un abonnement orderChanged qui écoute les modifications sur un Order. Lorsque nous recevons une mise à jour, nous souhaitons remplacer la commande dans notre requête orders par la commande mise à jour. Nous le faisons dans la fonction updateQuery dans subscribeToMore (mes excuses pour les fautes de frappe, ce n'est pas un copier-coller exacte):

componentDidMount() { 
    this.props.data.subscribeToMore({ 
    document: OrderSubscription, 
    variables: { 
     range: [0, 25] 
    }, 
    updateQuery: (prev, { subscriptionData, }) => { 
     // If no subscription data is passed, just return the previous 
     // result from the initial `orders` query 
     if (!subscriptionData.data) return prev 

     // get the data for the updated order from the subscription 
     const updatedOrder = subscriptionData.data.orderChanged 

     // find the index of the updated order from within the existing 
     // array of orders from the `orders` query 
     const existingOrderIndex = prev.orders.findIndex(order => (order.id === updatedOrder.id)) 

     // guard for missing data 
     if (existingOrderIndex) { 
     // replace the old order with the updated order 
     prev[existingOrderIndex] = updatedOrder 
     // return orders with new, updated data 
     return prev 
     } 

     return prev 
    }, 
    }) 
} 

Si vous pouviez me fournir une prise en pension minimale viable, je serais heureux de travailler par avec toi. J'ai passé une grande partie de la semaine dernière à travailler sur les abonnements :)

+0

Yeah s'avère que 'updateQuery' est un peu nécessaire. Je ne sais pas pourquoi j'ai eu l'impression qu'Apollo explorerait le résultat lui-même et mettrait à jour le magasin en fonction des types et de 'dataIdFromObject'. Tant pis. J'ai dû utiliser 'immutable-helper' pour une structure profondément imbriquée comme la mienne, mais cela semble fonctionner maintenant. Merci – FredyC