The primary idea of this hook is to re-create the underlying ApolloClient being used by all of the Subscription
and Query
components. There is lots of talk throughout the Apollo community about how to best refresh a WebSocket connection when a new auth token is available, and this is my attempt at providing something useful, apart from middleware that seems to have issues.
Related Links
- apollographql/subscriptions-transport-ws#171
- apollographql/apollo-link#197
- apollographql/subscriptions-transport-ws#102
- https://www.prisma.io/forum/t/authentication-issues-with-subscriptions/45?u=nilan
Architecturally, this solution keeps data flowing in the same direction, by passing a new apolloClient
down to the components that consume it whenever the auth token changes (after calling .stop()
on the current client). When downstream components receive this new prop, they reinstate their subscription connections as a part of their re-render, this time with the new token.
useApolloClient is essentially a wrapper around useState, which is holding a client instance. When the dispatch function is called with the new token (setApolloClient(token)
), a new client is created and the old client is replaced in State. The data then flows down through the Provider's components, triggering re-renders of all consumers.
In Auth0Provider, the idToken
(use any token you like in your own implementation) is also tracked in State, and on each re-render of the Auth0Provider, the current idToken
is compared with the token currently in use in the current apolloClient
, by reading from the cache (see Apollo Docs on managing local state):
const { idToken: cachedIdToken } = apolloClient.readQuery({ query: TOKEN_QUERY })
if (idToken !== cachedIdToken) {
apolloClient.stop()
setApolloClient(idToken)
}
In the event they do not match (because a new token is available, or the token has been cleared during a logout operation), the old client is stopped, cache is cleared (if that is a concern for security or whatever), and a new client is created.
I haven't yet profiled the memory or network overhead of this approach, but because this should be happening very rarely (once every couple hours at most, in the case of a refresh; and ideally when someone logs out/logs in, all of this should be rebuilt anyway, right?), I'm not overly concerned about performance in this regard. Unless the token changes, none of this re-rendering takes place.
Are you saying that you use SSE with Apollo Client's Subscription API?