ReactJS: Apollo Client set Authentication Token after User is Authenticated

Viewed 202

I have connected apollo client with my app. Initally there's no token in public route. Once the user logs in only then token is being fetched and stored.

My issue is that once user login I am not able to automatically set token in header for a query. Because I have initialized Apollo Client in the beginging I have to refresh the page to set the token in header. Is there any way in which I can set authentication token after login from login component ?

index.js

import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import { Provider } from "react-redux";
import { store } from "./redux/config-store";
import { PersistGate } from "redux-persist/integration/react";
import { persistStore } from "redux-persist";
import { ApolloProvider } from "@apollo/client";
import client from "./apollo/apollo.config";

let persistor = persistStore(store);

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={client}>
      <Provider store={store}>
        <PersistGate loading={null} persistor={persistor}>
          <BrowserRouter>
            <App />
          </BrowserRouter>
        </PersistGate>
      </Provider>
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

apolloconfig.js

import { setContext } from "@apollo/client/link/context";
import { store } from "../redux/config-store";

export const getToken = () => {
  const state = store.getState();
  if (state.currentUser.currentUser) {
    return state.currentUser.currentUser.token;
  } else {
    return "";
  }
};

const httpLink = createHttpLink({
  uri: "http://localhost:4000/graphql",
});

const authLink = setContext((_, { headers }) => {
  // get the authentication token from local storage if it exists
  const token = getToken();
  // return the headers to the context so httpLink can read them
  return {
    headers: {
      ...headers,
      authorization: `${token}`,
    },
  };
});

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

export default client;

How do I set token automatically after user is logged in?

1 Answers

After some research I have figured out a solution for this. Posting solution if anyone else has encountered this problem.

In index.js, client is created using new ApolloClient and passed to Apollo Provider as shown

export const apolloClient = new ApolloClient({
  uri: "http://localhost:4000/graphql",
  cache: new InMemoryCache({
    addTypename: false,
  }),
});

ReactDOM.render(
  <React.StrictMode>
    <ApolloProvider client={apolloClient}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </ApolloProvider>
  </React.StrictMode>,
  document.getElementById("root")
);

In cases where authentication is required the token is passed on individual queries as shown,

const { loading, error, data } = useQuery(EXAMPLE_QUERY, {
    context: {
          headers: {
            authorization: `${
              user.accessToken ? user.accessToken : ""
            }`,
          },
        },
  });

I am not sure if this the most efficient solution. But this works for me without any issues.

Related