0

I want to set auth in req header to specific value but after I tried different methods and check req from browser my key is not in the req header

I am using Reactjs ,vite ,@apollo/client and running inside docker

import {
  ApolloClient,
  InMemoryCache,
  HttpLink,
  ApolloLink,
} from '@apollo/client';
import { setContext } from '@apollo/client/link/context';


 const httpLink = new HttpLink({
  uri: 'http://localhost:4000/graphql',
});

I tried with setContext

const authMiddleware = setContext(async (_, { headers }) => {
  const token = localStorage.getItem('token');

  return {
    headers: {
      ...headers,
      'Authorization': `Bearer ${token}` || '',
    },
  };
});

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

I tried with ApolloLink

const authMiddleware = new ApolloLink((operation, forward) => {
  // add the authorization to the headers

  operation.setContext(() => ({
    headers: {
       'Authorization': `Bearer ${token}` || '',
    },
  }));

  return forward(operation);
});

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

My used version for react and @apollo/client

"@apollo/client": "^3.11.8",
"react": "^18.3.1",

This is where I wrap my component with ApolloProvider

import { ApolloProvider } from '@apollo/react-hooks';
import { client } from './config/graphql.ts';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <ApolloProvider client={client}>
    <React.StrictMode>
          <App />
    </React.StrictMode>
  </ApolloProvider>

My data fetch req

   const response = await axios.post('http://localhost:4000/graphql', {
      query: GET_USERS,
    });

but nothing work as you see my header don't have the Authorization key

enter image description here

2 Answers 2

1

I figured out what cause this so I will put my answer here for anyone come across my case

I was calling the query wrong in redux action

Error

  const response = await axios.post('http://localhost:4000/graphql', {
      query: GET_USERS,
    });

Correct

const { data, error } = await client.query({
  query: GET_USERS, // The GraphQL query
});

so this should depend on the client I created

export const client = new ApolloClient({
  link,
  cache: new InMemoryCache(),
});
Sign up to request clarification or add additional context in comments.

6 Comments

Also, keep in mind that 99% of the time you should not be doing this in Redux at all. If you are using Apollo Client, you already have a cache, you should not duplicate that data over multiple caches. You can use Redux for everything else, but not for the data from your GraphQL server. That's what you have Apollo Client for. Just use the Apollo Client hooks in your components.
and how I can pass data between my different components with Apollo client as at some point I need to share these info between my app components @phry
You use these hooks in multiple places. useQuery doesn't make a network request if it already has received the data in the past and it's in the cache.
I was wonder if using useQuery in any component I want just to share data in is consider best practice
You can also use e.g. use useFragment to access the data if you are sure the data is already fetched. Also, use props, the point of Redux is not to avoid using props. But please don't copy data from Apollo Client into Redux state unless you have a very good reason to do so. I'm saying that as a maintainer of both Apollo Client and Redux.
|
-2

Authorization in headers should be in lowercase "authorization" and set your method to below one for better error handling.

const authMiddleware = new ApolloLink(
(operation, forward) =>
  new Observable((observer) => {
    let handle;
    Promise.resolve(operation)
      .then((oper) => request(oper))
      .then(() => {
        handle = forward(operation).subscribe({
          next: observer.next.bind(observer),
          error: observer.error.bind(observer),
          complete: observer.complete.bind(observer),
        });
      })
      .catch(observer.error.bind(observer));

    return () => {
      if (handle) handle.unsubscribe();
    };
  }));

const request = async (operation) => {
const data = localStorage.getItem("token");

let token = null;
if (data) {
  token = data;
}
operation.setContext({
  headers: {
    authorization: token ? `Bearer ${token}` : "",
  },
})};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.