Jan Schmutz
Jan Schmutz

Reputation: 890

Apollo GraphQL: Change default Header INSIDE React Child Component

I'm trying to change the default header of my Apollo Graph QL Client INSIDE a react component and I simply cant manage to find anything in the docs. So in my index.js I create and link my client as described and add a JWT Token header. But what if I want to change the headers inside my React Component. For example, I want to replace the Token on reauthenticate.

In Axios you can simply do something with this.

axios.defaults.headers.common['Auth-Token'] = 'foo bar';

How can I do something like that with React Apollo? Here is he important part of my index.js

const httpLink = createHttpLink({
    uri: 'https://somesecureapi',
});

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()
});

I tried to export the client and then import it to the component create a new Link and changethe old one but this didn't work.

There must be some easier way for this. Any suggestions

Upvotes: 1

Views: 2854

Answers (1)

Jackyef
Jackyef

Reputation: 5012

createHttpLink accept fetch options, in which you can custom how you want your fetch to behave. A simple implementation could look like this:

import { ApolloProvider, graphql } from "react-apollo";
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloLink } from "apollo-link";
import { createHttpLink } from "apollo-link-http";

const customFetch = (uri, options) => {
  return fetch(uri, {
    ...options,
    headers: {
      ...options.headers,
      "x-custom-header": "custom value"
    }
  });
};

const fetchLink = createHttpLink({
  uri: "https://graphql-pokemon.now.sh",
  fetch: customFetch
});

const client = new ApolloClient({
  link: ApolloLink.from([fetchLink]),
  cache: new InMemoryCache()
});

As you can see in customFetch, I added x-custom-header with "custom value". This will be applied to all query that uses this client. But, I am also spreading options.headers for the fetch options, so any headers that come will be passed through.

In our component, we can pass extra headers like this:

const WrappedPokemon = graphql(PokemonQuery, {
  options: {
    context: { headers: { "x-another-custom-header": "another custom value" } }
  },
  props: ({ data }) => ({
    loading: data.loading,
    pokemon: data.pokemon || {}
  })
})(Pokemon);

This extra header will only exist for this query only, unlike the one above.

I have made a simple implementation in codesandbox to help you understand the implementation.

The result looks like this: The custom headers are getting passed through, yay!

Upvotes: 6

Related Questions