I am trying to implement the Authentication workflow officially described in the Apollo docs as I did before in other projects, but this time using Gatsby.
The idea seems pretty straightforward. Need to create/update gatsby-browser.js
like when using redux but to initialise the ApolloClient
and pass through ApolloProvider
.
Something like:
import React from 'react'
import { Router } from 'react-router-dom'
import { ApolloProvider } from 'react-apollo'
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { setContext } from 'apollo-link-context'
const httpLink = createHttpLink({
uri: process.env.ENDPOINT_URI,
credentials: 'same-origin',
})
const authLink = setContext((_, { headers }) => {
const token = localStorage.getItem('token');
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
}
}
})
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache().restore({}),
})
exports.replaceRouterComponent = ({ history }) => {
const ConnectedRouterWrapper = ({ children }) => (
<ApolloProvider client={client}>
<Router history={history}>{children}</Router>
</ApolloProvider>
)
return ConnectedRouterWrapper
}
Then login using
<Mutation
mutation={LOGIN_MUTATION}
refetchQueries={[{ query: CURRENT_USER_QUERY }]}
>
{/*...*/}
</Mutation>
and in another Component with something like the Status (where, if logged in shows x otherwise y):
<Query query={CURRENT_USER_QUERY} fetchPolicy="network-only">
{/*...*/}
</Query>
The problem
With this configuration, when the login receives data
(so, credentials are ok), I save the token received in localStorage
but the Status component do the Query
with the previous (empty) token
, so shows logged out, also doing something like history.push('/')
after login.
Refreshing the page, since the item in localStorage
was saved before, the Status shows as logged in.
Expected behaviour
The idea is to have the Status component updated after login avoiding doing a refresh of the page, for this reason I added refetchQueries={[{ query: CURRENT_USER_QUERY }]}
.
I tried some things like pass props
(no needed in case I change the route
and use withRouter
in the Status component), but seems to late, the Query
was fired without the new token
.