Skip to content

Instantly share code, notes, and snippets.

@polRk
Last active May 11, 2020 16:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save polRk/83fafc09240ae2ad1e682332a5c6199c to your computer and use it in GitHub Desktop.
Save polRk/83fafc09240ae2ad1e682332a5c6199c to your computer and use it in GitHub Desktop.
React Apollo useClient with authorization
import {
ApolloClient,
ApolloLink,
HttpLink,
InMemoryCache,
} from '@apollo/client'
import { getMainDefinition } from '@apollo/client/utilities'
import { setContext } from '@apollo/link-context'
import { onError } from '@apollo/link-error'
import { RetryLink } from '@apollo/link-retry'
import { WebSocketLink } from '@apollo/link-ws'
import { useNavigate } from 'react-router'
export const useAuthLink = () => {
return setContext((_, { headers }) => {
const token = localStorage.getItem('token')
return { headers: { Authorization: `Bearer ${token}` } }
})
}
export const useErrorLink = () => {
const navigate = useNavigate()
return onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
for (let err of graphQLErrors) {
switch (err.extensions?.code) {
case 'access-denied':
navigate('/login')
break
case 'invalid-jwt':
localStorage.removeItem('token')
navigate('/login')
break
}
}
}
})
}
export const useRetryLink = () => {
return new RetryLink({
delay: {
initial: 500,
max: Infinity,
jitter: true,
},
attempts: {
max: 5,
retryIf: error => !!error,
},
})
}
export const useLink = () => {
const token = localStorage.getItem('token')
const httpLink = new HttpLink({
uri: process.env.REACT_APP_HASURA_API_URL || '/graphql',
headers: { Authorization: `Bearer ${token}` },
})
const wsLink = new WebSocketLink({
uri: process.env.REACT_APP_HASURA_WSS_URL || '/graphql',
options: {
reconnect: true,
lazy: true,
connectionParams: () => {
const token = localStorage.getItem('token')
return { headers: { Authorization: `Bearer ${token}` } }
},
connectionCallback: console.log,
},
})
return ApolloLink.split(
({ query }) => {
const definition = getMainDefinition(query)
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
wsLink,
httpLink
)
}
export const useClient = () => {
const authLink = useAuthLink()
const errorLink = useErrorLink()
const retryLink = useRetryLink()
const link = useLink()
return new ApolloClient({
cache: new InMemoryCache(),
link: ApolloLink.from([authLink, retryLink, errorLink, link]),
connectToDevTools: true,
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment