Search code examples
apolloreact-apolloapollo-clientapollostack

Apollo: Update React Props on Subscription Update?


Looking at the Apollo docs example code for subscriptions, I am not yet seeing how to update the React props with the subscription results.

From http://dev.apollodata.com/react/subscriptions.html:

Here is a regular query:

import { CommentsPage } from './comments-page.js';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
const COMMENT_QUERY = gql`
    query Comment($repoName: String!) {
      entry(repoFullName: $repoName) {
        comments {
          id
          content
        }
      }
    }
`;
const withData = graphql(COMMENT_QUERY, {
    name: 'comments',
    options: ({ params }) => ({
        variables: {
            repoName: `${params.org}/${params.repoName}`
        },
    })
});
export const CommentsPageWithData = withData(CommentsPage);

Now, let’s add the subscription.

Note that this sample code appears to leave out this part of the props code for usual queries - from http://dev.apollodata.com/react/queries.html:

  props: ({ ownProps, data: { loading, currentUser, refetch } }) => ({
    userLoading: loading,
    user: currentUser,
    refetchUser: refetch,
  }),

...which AFAIK is the correct way to update the data props on my React component and trigger a page refresh.

Here is the complete subscription code sample from http://dev.apollodata.com/react/subscriptions.html:

const withData = graphql(COMMENT_QUERY, {
    name: 'comments',
    options: ({ params }) => ({
        variables: {
            repoName: `${params.org}/${params.repoName}`
        },
    }),
    props: props => {
        return {
            subscribeToNewComments: params => {
                return props.comments.subscribeToMore({
                    document: COMMENTS_SUBSCRIPTION,
                    variables: {
                        repoName: params.repoFullName,
                    },
                    updateQuery: (prev, {subscriptionData}) => {
                        if (!subscriptionData.data) {
                            return prev;
                        }
                        const newFeedItem = subscriptionData.data.commentAdded;
                        return Object.assign({}, prev, {
                            entry: {
                                comments: [newFeedItem, ...prev.entry.comments]
                            }
                        });
                    }
                });
            }
        };
    },
});

How do I get the code shown here, to update the data props on my React component and trigger a page refresh, when the results come in from the non-subscription query COMMENT_QUERY?


Solution

  • Thanks to @neophi on the Apollo Slack for this answer!

    const withDataAndSubscription = graphql(GETIMS_QUERY, {
        options({toID}) {
            console.log(GETIMS_QUERY);
            const fromID = Meteor.userId();
            return {
                fetchPolicy: 'cache-and-network',
                variables: {fromID: `${fromID}`, toID: `${toID}`}
            };
        }
        ,
        props: props => {
            return {
                loading: props.data.loading,
                instant_message: props.data.instant_message,
                subscribeToMore: props.data.subscribeToMore,
                subscribeToNewIMs: params => {
                    const fromID = Meteor.userId();
                    const toID = params.toID;
                    return props.data.subscribeToMore({
                        document: IM_SUBSCRIPTION_QUERY,
                        variables: {fromID: `${fromID}`, toID: `${toID}`},
                        updateQuery: (previousResult, {subscriptionData}) => {
                            if (!subscriptionData.data) {
                                return previousResult;
                            }
                            const newMsg = subscriptionData.data.createIM;
                            return update(previousResult, {
                                instant_message: {
                                    $push: [newMsg],
                                },
                            });
                        }
                    });
                }
            };
        },
    })
    ;