In the docs for Subscriptions, the example for subscribeForMore
shows a CommentsPageWithData
passing a callback (which will actually call subscribeForMore
) into a child component, CommentsPage
, which calls the callback in a useEffect
hook. Why is that? What would be wrong with moving the useEffect
call up into CommentsPageWithData
?
E.g.
function CommentsPageWithData({ params }: CommentsPageWithDataProps) {
const { subscribeToMore, ...result } = useQuery(
COMMENTS_QUERY,
{ variables: { postID: params.postID } }
);
useEffect(() => {
subscribeToMore({
document: COMMENTS_SUBSCRIPTION,
variables: { postID: params.postID },
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const newFeedItem = subscriptionData.data.commentAdded;
return Object.assign({}, prev, {
post: {
comments: [newFeedItem, ...prev.post.comments]
}
});
});
});
});
return (
<CommentsPage {...result} />
);
}
More on the design of the Apollo Client library, I’m also curious why useQuery
couldn’t take a subscribeForMore
-like option directly, rather than requiring it to be called back? It seems like the current design is made to be analagous to fetchMore
, but that would usually be initiated by a user action, whereas I would think subscribeForMore
would often want to be initiated immediately after the query completes, with access to the result of the query.
E.g.
function CommentsPageWithData({ params }: CommentsPageWithDataProps) {
const { subscribeToMore, ...result } = useQuery(
COMMENTS_QUERY,
{
variables: { postID: params.postID },
subscribeToMore((data) => ({
document: COMMENTS_SUBSCRIPTION,
variables: { postID: params.postID },
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const newFeedItem = subscriptionData.data.commentAdded;
return Object.assign({}, prev, {
post: {
comments: [newFeedItem, ...prev.post.comments]
}
});
})),
}),
},
);
return (
<CommentsPage {...result} />
);
}