Use API token in axios instance in react native app

Viewed 984

I am trying to create an axios instance that I can use throughout the app. I used this same pattern in Vue using Vuex store but not sure how to do this in React. I have an AuthProvider for AuthContext and would like to useContext when creating the axios instance but I'm receiving an error that I can't use useContext outside of a component.

What is the best way to accomplish this? I have the user and a logout function in the AuthContext that I would like to use but this pattern may not be best for React.

import React, { useContext } from "react";
import axios from 'axios'
import { AuthContext } from "./AuthProvider";
import { getEnvironment } from "./environment";
const env = getEnvironment();

const { user, logout } = useContext(AuthContext);

const instance = axios.create();

instance.defaults.baseURL = env.apiUrl;

instance.defaults.headers.common['Authorization'] = `Bearer ${user.token}`;

instance.interceptors.response.use(function (response) {
  return response
}, function (error) {
  if (typeof error.response === 'undefined' || [401, 419].includes(error.response.status)) {
    logout();
  }
  return Promise.reject(error)
})

export default instance;

1 Answers

I think if you want to couple some state and callbacks from another context then you need to create another context and axios instance provider of your own as well.

import React, { createContext, useEffect, useContext } from "react";
import axios from 'axios'
import { AuthContext } from "./AuthProvider";
import { getEnvironment } from "./environment";

const env = getEnvironment();

const instance = axios.create(); // <-- create axios instance
instance.defaults.baseURL = env.apiUrl;

export const AxiosContext = createContext(null); // <-- export axios context

const AxiosProvider = ({ children }) => {
  const { user, logout } = useContext(AuthContext); // <-- get state/callback

  // Use an effect to updated the auth context dependent details
  useEffect(() => {
    instance.defaults.headers.common['Authorization'] = `Bearer ${user.token}`;
    instance.interceptors.response.use(function (response) {
      return response
    }, function (error) {
      if (typeof error.response === 'undefined' || [401, 419].includes(error.response.status)) {
        logout();
      }
      return Promise.reject(error);
    });
  }, [user.token, logout]);
  

  return (
    <AxiosContext.Provider value={instance}> // <-- context value is instance
      {children}
    </AxiosContext.Provider>
  );
}

export default AxiosProvider; // <-- export the provider not the instance

To use just ensure that AxiosProvider wraps your application but within the auth provider. Use the AxiosContext to access the axios instance.

import { AxiosContext } from '../path/to/axios/instance";

...

const axiosInstance = useContext(AxiosContext);

...
Related