Use state token inside axios instance

Viewed 56

I have a state with a token that i get from my api :

const initialState = {
  isAuth: false,
  token: "",
};

And I want to reuse the token in an Axios instance :

const api = axios.create({
  baseURL: `${baseUrl}`,
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

export default api;

The problem is that I can not read the token via useSelector as :

const token = useSelector((state) => state.auth.token);

I get the error message :

invalid hook call. hooks can only be called inside of the body of a function component

Any suggestion ? Thanks in advance

4 Answers

You can't use hooks outside of function components or other hooks. However, you can create the axios instance without the token, and then update the instance (api) when you have it (see axios's Config Defaults).

Note: you'll need to prevent your app from using the axios instance before the token is set.

Define the api without the authorization header:

const api = axios.create({
  baseURL: `${baseUrl}`,
});

In one of your top components get the token, and apply it to the axios instance defaults:

const App = () => {
  const token = useSelector((state) => state.auth.token);

  useEffect(() => {
    if(token) {
      api.defaults.headers.common['Authorization'] = `Bearer ${token}`;
    }
  }, [token]);
}

It is because a hook can only be used inside a React Component. To be able to retrieve this state, the ideal is to store it in the localStorage. The localStorage can be accessed at any level (React components or not)

You need to create a new value in the localStorage in this way:

localStorage.setItem("myToken",value)

Then you can use it inside the axios instance like this :

localStorage.getItem("myToken")

Also, I advice you to use the interceptors for axios to handle the token it's better

Hope it helps !

imo you should also use the Interceptors for axios to handle the accesstoken

Resource https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

I'm not really sure where your useSelector is called exactly (and also where the other code fragments are placed inside your code) but your specific error message makes it clear, that your are calling the useSelector-hook not directly inside a functional component.

I would suggest you to read the following article: Hooks Rules

There it says:

Don’t call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns

One option might be to wrap your Axios code in a custom hook function. This will allow you to use other hook functions – including accessing your Redux state via useSelector.

For example:

const useApi = () => {
  const token = useSelector((state) => state.auth.token);

  const api = axios.create({
    baseURL: `${baseUrl}`,
    headers: {
      Authorization: `Bearer ${token}`,
    },
  });

  return api;
}

export default useApi;
Related