2021年5月3日星期一

Detecting if Apollo has finished configuration before allowing queries

I have a React SPA with following top-level structure. I'm using Auth0 for authentication and Apollo Client for queries and React Context to provide a global state.

The problem I'm having is that a query made in my global state is executing before the Apollo Client can complete configuration of its header (namely, inserting a token via Auth0).

Is there a way (perhaps using the useApolloClient hook to tell if Apollo has a token in its authLink? Or another way to achieve the objective of delaying initialization of Global State until its parent component AuthorizedApolloProvider has completed?

<BrowserRouter>    <Auth0ProviderWithHistory>      <AuthorizedApolloProvider>        <GlobalState>          <App />        </GlobalState>      </AuthorizedApolloProvider>    </Auth0ProviderWithHistory>  </BrowserRouter>  

Within AuthorizedApolloProvider, I am setting context for Apollo by inserting a token on all queries as follows:

const AuthorizedApolloProvider = ({children}) => {      const { getAccessTokenSilently } = useAuth0()      const httpLink = createHttpLink ({      uri: uriGQL, // a config parameter    })        const authLink = setContext(async () => {      const token = await getAccessTokenSilently()      console.log('Got the token..... ', token.substring(0, 10))      return {        headers: {          authorization: token ? token : ""        }      }    })      let links = [authLink, httpLink]      const client = new ApolloClient({      link: ApolloLink.from(links),      cache: new InMemoryCache({        addTypename: false,      }),    })      console.log('Rendering ApolloProvider')      return(      <ApolloProvider client={client}>        {children}      </ApolloProvider>    )  }  

Next, in Global State, I am sending a GQL query to fetch information about the user who has logged in as follows:

  const GlobalState = props => {      const { user: auth0User, isLoading, isAuthenticated } = useAuth0()      const client = useApolloClient()      const [state, setState] = useState(initialState)      const [ getUser, { loading, data, error }] = useLazyQuery(GET_USER)        const history = useHistory()        useEffect(async () => {        // Has useAuth0 returned?      if(isLoading===false) {        console.log('isAuthenticated=', isAuthenticated)        console.log('auth0User', auth0User)          // Is authenticated?        if(!isAuthenticated) {          // If not authenticated...          console.log('Not authenticated')          localStorage.removeItem('user')          setState({ ...state, loaded: true, user: null })        }        else {          // If authenticated...          // Check to see if user object is in local storage          let user = await localStorage.getItem('user')          if(user) {            console.log('Authenticated, found user in local storage')            // User found in local storage            user = JSON.parse(user)            setState({ ...state, loaded: true, user: user })          }          else {            // User not found in local storage. Must fetch from server            console.log('Authenticated, getting user from server')              try {              console.log('Calling getUser...')              const result = await getUser()            }            catch (error) {              console.log(error)            }          }        }      }      }, [isLoading])    ...    

The problem I'm having is that the getUser query is being called before the Apollo client can finish configuring.

When I run the code, I see that the below fragment...

try {     console.log('Calling getUser...')     const result = await getUser()  }  

...is being executed before the following...

console.log('Got the token..... ', token.substring(0, 10))      return {        headers: {          authorization: token ? token : ""        }      }  
https://stackoverflow.com/questions/67378001/detecting-if-apollo-has-finished-configuration-before-allowing-queries May 04, 2021 at 10:24AM

没有评论:

发表评论