'Setting Apollo client header dynamically is not working

I am trying to set the header of Apollo client dynamically according to official doc, but I am getting an error:

    TypeError: (0 , _apollo.default) is not a function

This is my apollo.js

import { ApolloClient } from 'apollo-client';
import { createHttpLink } from 'apollo-link-http';
import { setContext } from 'apollo-link-context';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { AsyncStorage } from 'react-native';

const httpLink = createHttpLink({
    uri: 'http://192.168.2.4:8000/api/',
});

const authLink = setContext((_, { headers }) => {
    const token = AsyncStorage.getItem('token');

    return {
        headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : "",
        }
    }
});

const client = new ApolloClient({
    link: authLink.concat(httpLink),
    cache: new InMemoryCache()
});

export default client; 

UPDATE

I am adding App.js:

import { ApolloProvider } from 'react-apollo';
import Routes from './app/config/routes';
import makeApolloClient from './app/config/apollo';

export default function App() {
  const client = makeApolloClient();

  return (
    <ApolloProvider client={client}>
      <Routes />
    </ApolloProvider>);
}

How can I solve this issue?



Solution 1:[1]

makeApolloClient isnt a function, the file just exports an instance of the apollo client. Just import it as if it's a variable.

import client from './app/config/apollo'

export default function App() {
    return (
        <ApolloProvider client={client}>
          <Routes />
        </ApolloProvider>
    );
}

Solution 2:[2]

Apollo usequery has a context option that allows you to dynamically change or update the values of the header object.

import { ApolloClient, InMemoryCache } from "@apollo/client";

const client = new ApolloClient({
  cache: new InMemoryCache(),
  uri: "/graphql"
});

client.query({
  query: MY_QUERY,
  context: {
    // example of setting the headers with context per operation
    headers: {
      special: "Special header value"
    }
  }
});

The code above was copied from the Apollo docs. To find out more check out https://www.apollographql.com/docs/react/networking/advanced-http-networking/#overriding-options

Solution 3:[3]

Try this

const authLink = setContext(async (_, { headers }) => {
    const token = await AsyncStorage.getItem('token');

    return {
        headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : "",
        }
    }
});

Solution 4:[4]

This code automatically reads and sets Authorization header after localStorage.setItem('jwt_token', jwt_token) in SignIn mutation.

import {ApolloClient, createHttpLink} from "@apollo/client";
import {setContext} from "@apollo/client/link/context";
import {InMemoryCache} from "@apollo/client";

const apolloHttpLink = createHttpLink({
    uri: process.env.REACT_APP_APOLLO_SERVER_URI || 'http://localhost/graphql',
})

const apolloAuthContext = setContext(async (_, {headers}) => {
    const jwt_token = localStorage.getItem('jwt_token')
    return {
        headers: {
            ...headers,
            Authorization: jwt_token ? `Bearer ${jwt_token}` : ''
        },
    }
})

export const apolloClient = new ApolloClient({
    link: apolloAuthContext.concat(apolloHttpLink),
    cache: new InMemoryCache(),
})

Solution 5:[5]

In React Native, AsyncStorage methods are async not like localStorage in Web. And the other methods doesn't work, except this.

https://github.com/apollographql/apollo-client/issues/2441#issuecomment-718502308

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jack Clackett
Solution 2 David Buck
Solution 3
Solution 4 Eugene Zalivadnyi
Solution 5 MoonTaeTae