Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useContext inside axios interceptor

I cant figure out why my useContext is not being called in this function:

import { useContext } from "react";
import { MyContext } from "../contexts/MyContext.js";
import axios from "axios";

const baseURL = "...";

const axiosInstance = axios.create({
  baseURL: baseURL,
  timeout: 5000,
.
.
.
});
axiosInstance.interceptors.response.use(
  (response) => response,
  async (error) => {
    const { setUser } = useContext(MyContext);
    console.log("anything after this line is not running!!!!");
    setUser(null)

.
.
. 

My goal is to use an interceptor to check if the token is live and if its not clear the user and do the login. I'm using the same context in my other react components. And its working fine there, its just not running here! any idea whats I'm doing wrong?

like image 755
Farrokh Rostami Kia Avatar asked Oct 10 '20 17:10

Farrokh Rostami Kia


People also ask

How do you use react hooks in Axios interceptors?

import axios from 'axios'; const instance = axios. create({ baseURL: "https://example.com" }) export default instance; As we need React component to use the hooks, let's write a component here. Adding an interceptor in a component is a side effect, so we get help from useEffect hook.

Can we use Axios in useEffect?

To use Axios with the useEffect hook, we just define an async function and call it inside the useEffect callback. Alternatively, we can use the useAxios hook provided by the axios-hooks library.


1 Answers

I had the same issue as you. Here is how I solved it:

You can only use useContext inside a functional component which is why you can't execute setUser inside your axios interceptors.

What you can do though is to create a separate file called WithAxios:

// WithAxios.js

import { useContext, useMemo } from 'react'
import axios from 'axios'

const WithAxios = ({ children }) => {
    const { setUser } = useContext(MyContext);

    useMemo(() => {
        axios.interceptors.response.use(response => response, async (error) => {
            setUser(null)
        })
    }, [setUser])

    return children
}

export default WithAxios

And then add WithAxios after MyContext.Provider to get access to your context like this for example:

// App.js

const App = () => {
    const [user, setUser] = useState(initialState)

    return (
        <MyContext.Provider value={{ setUser }}>
            <WithAxios>
                {/* render the rest of your components here  */}
            </WithAxios>
        </MyContext.Provider>
    )
}
like image 65
Anatol Avatar answered Nov 10 '22 19:11

Anatol