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} />
);
}