# Axios 🚀

## GET Request

we can do either `axios.get(url)` or `axios(url)` for GET request.

```javascript
import { useEffect } from 'react'
// limit, if 429 wait for 15 min and try again

import axios from 'axios'
const url = 'https://course-api.com/react-store-productss'

const fetchData = async () => {
  try {
    const { data } = await axios(url)
    console.log(data)
  } catch (error) {
    // if you just do error here, it won't show you the object
    console.log(error.response) 
  }
}

const FirstRequest = () => {
  useEffect(() => {
    fetchData()
    console.log('first axios request')
  }, [])

  return <h2 className="text-center">first request</h2>
}
export default FirstRequest
```

<figure><img src="https://1944679227-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVEiPUp08kYt33g51v7%2Fuploads%2FkuCo2fegIf4DqjoAQqf2%2Fimage.png?alt=media&#x26;token=f21ddc12-6f2e-434c-8dbc-78268a33edae" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1944679227-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVEiPUp08kYt33g51v7%2Fuploads%2F3wu5k2np22e3GWRQaEBC%2Fimage.png?alt=media&#x26;token=7f2e6760-1579-41f4-9cef-441bbffc54b1" alt=""><figcaption><p>error.response</p></figcaption></figure>

## Headers

We need to provide headers for POST and PATCH request. Some times in some apis we also need to provide headers for GET request.

```javascript
const { data } = await axios(url, {
    headers: {// if we don't put this headers and accept json, we get a text instead of json
      Accept: 'Application/json',
    },
})
```

```javascript
import { useState } from 'react'
import axios from 'axios'

const url = 'https://icanhazdadjoke.com/'
// Accept : 'application/json'

const Headers = () => {
  const [joke, setJoke] = useState('random dad joke')

  const fetchData = async () => {
    try {
      const { data } = await axios(url, {
        headers: {
          Accept: 'Application/json',
        },
      })
      setJoke(data.joke)
    } catch (error) {
      console.log(error.response)
    }
  }

  const fetchDadJoke = async () => {
    fetchData()
  }

  return (
    <section className="section text-center">
      <button className="btn" onClick={fetchDadJoke}>
        random joke
      </button>
      <p className="dad-joke">{joke}</p>
    </section>
  )
}
export default Headers
```

{% hint style="info" %}
In GET Request, the headers will be 2nd parameter like this&#x20;

```javascript
axios(url, {headers:{}} )
// OR
axios.get(url, {headers:{}} )
```

In POST/PATCH Request, since we will also be sending the body, the body will be 2nd param and headers will be 3rd param

<pre class="language-javascript"><code class="lang-javascript"><strong>axios.post(url, data, {headers:{}} )
</strong></code></pre>

{% endhint %}

## POST Request

```javascript
import { useState } from 'react'
import axios from 'axios'
const url = 'https://course-api.com/axios-tutorial-post'

const PostRequest = () => {
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')

  const handleSubmit = async (e) => {
    e.preventDefault()
    try {
      const resp = await axios.post(url, { name, email })
      console.log(resp)
    } catch (error) {}
  }

  return (
    <section>
      <h2 className="text-center">post request</h2>
      <form className="form" onSubmit={handleSubmit}>
        <div className="form-row">
          <label htmlFor="name" className="form-label">
            name
          </label>
          <input
            type="text"
            className="form-input"
            id="name"
            value={name}
            onChange={(e) => setName(e.target.value)}
          />
        </div>
        <div className="form-row">
          <label htmlFor="email" className="form-label">
            email
          </label>
          <input
            type="email"
            className="form-input"
            id="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
          />
        </div>
        <button type="submit" className="btn btn-block">
          login
        </button>
      </form>
    </section>
  )
}
export default PostRequest
```

## Global Defaults

We can add global defaults to axios. That means every time we make a axios request, that functionality will be added. For example, we can add these defaults in one file and import them

```javascript
axios.defaults.headers.common['Accept'] = 'application/json';
axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] =
  'application/x-www-form-urlencoded';
```

Let's say we add first one (headers), then every request will accept application/json and we don't need to add to individual requests.

We need to create a new JS file for axios configuration like this

{% code title="axios/global.js" %}

```javascript
import axios from 'axios'

axios.defaults.headers.common['Accept'] = 'application/json'
```

{% endcode %}

We have created axios folder and inside that, we have a file `global.js` where all axios defaults go.

Then we need to import this file in main file App.js or index.js like this&#x20;

{% code title="App.js or index.js" %}

```javascript
import './axios/global'
```

{% endcode %}

Now we can use axios in the component file as ususal

{% code title="GlobalInstance.js" %}

```javascript
import { useEffect } from 'react'
import axios from 'axios'
const productsUrl = 'https://course-api.com/react-store-products'
const randomUserUrl = 'https://randomuser.me/api'

const GlobalInstance = () => {
  const fetchData = async () => {
    try {
    
      /* both resp1 and resp2 will have request headers - application/json because
      of global settings done above */
      
      const resp1 = await axios(productsUrl) 
      const resp2 = await axios(randomUserUrl)
      console.log(resp1)
      console.log(resp2)
    } catch (error) {
      console.log(error.response)
    }
  }

  useEffect(() => {
    fetchData()
  }, [])

  return <h2 className="text-center">global instance</h2>
}
export default GlobalInstance
```

{% endcode %}

both `resp1` and `resp2` will have request headers - application/json because of global settings of axios. We might not need this setting to one of the individual axios request sometimes, so let's see how to solve that using custom instance

## Custom Instance

Here instead of global instance we use custom instance where we can create axios functions that have some defaults and we can use it where we want

{% code title="axios/custom.js" %}

```javascript
import axios from 'axios'

const authFetch = axios.create({
  baseURL: 'https://course-api.com', // this would be the root url
  headers: {
    Accept: 'application/json',
  },
})

export default authFetch
```

{% endcode %}

{% code title="CustomInstance.js" %}

```javascript
import axios from 'axios'
import { useEffect } from 'react'
import authFetch from '../axios/custom'

const randomUserUrl = 'https://randomuser.me/api'

const CustomInstance = () => {
  const fetchData = async () => {
    try {
      // the full url will be baseURL + this one  = https://course-api.com/react-store-products
      const resp1 = await authFetch('/react-store-products') // this req has accept : application/json only and no text
      const resp2 = await axios(randomUserUrl) // this is normal axios request
    } catch (error) {}
  }

  useEffect(() => {
    fetchData()
  }, [])

  return <h2 className="text-center">custom instance</h2>
}
export default CustomInstance

```

{% endcode %}

The below request has application/json

```javascript
// this req has accept : application/json only and no text
const resp1 = await authFetch('/react-store-products') 
```

<figure><img src="https://1944679227-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVEiPUp08kYt33g51v7%2Fuploads%2FClCLzuFKactCN8ObBtAP%2Fimage.png?alt=media&#x26;token=56f28785-c070-42e8-83ab-a9cf8f2dd066" alt=""><figcaption></figcaption></figure>

The below second request is a normal axios request so it has both application/json and text

```javascript
// this is a normal axios req that doesn't have any defaults
const resp2 = await axios(randomUserUrl) 
```

<figure><img src="https://1944679227-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVEiPUp08kYt33g51v7%2Fuploads%2FznzkrdHLEAwBqxbSDDwM%2Fimage.png?alt=media&#x26;token=37f31925-7789-46ac-9b84-e9f20d23d4cc" alt=""><figcaption></figcaption></figure>

## Interceptors

These are the axios functions that can be called before the request is sent and/or after getting the response.

<figure><img src="https://1944679227-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVEiPUp08kYt33g51v7%2Fuploads%2F4qCcc3H50wI1PLNDWUPx%2Fimage.png?alt=media&#x26;token=6dbcc166-1933-410e-b593-cfdacc9031c4" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1944679227-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVEiPUp08kYt33g51v7%2Fuploads%2FFYVmqmrD4BviR9MyegFf%2Fimage.png?alt=media&#x26;token=5d467240-f5b4-490f-a625-3a8c5d1d4e79" alt=""><figcaption></figcaption></figure>

Interceptors make more sense when we have complex applications for example if we have authentication in a big app. This is just an intro to interceptors and we can take a look later in projects as and when we need (*I'll update this notes with more info as I come across it)*

We will use `CustomImplementation` of axios and not global one in our example. We could also use Global ones, just fyi.

*Component that uses interceptor that is used in App.js*

{% code title="Component that uses Interceptor" %}

```javascript
import { useEffect } from 'react'
import authFetch from '../axios/interceptor'

const url = 'https://course-api.com/react-store-products'

const Interceptors = () => {
  const fetchData = async () => {
    try {
      const resp = await authFetch('/react-store-products') // we already have first half of url as baseURL in authFetch
      console.log(resp)
    } catch (error) {}
  }

  useEffect(() => {
    fetchData()
  }, [])

  return <h2 className="text-center">interceptors</h2>
}
export default Interceptors

```

{% endcode %}

The request and response interceptors in authFetch

{% code title="axios/interceptor.js" %}

```javascript
import axios from 'axios'

const authFetch = axios.create({
  baseURL: 'https://course-api.com',
  // Lets put the below in interceptor
  //   headers: {
  //     Accept: 'application/json',
  //   },
})

// REQUEST INTERCEPTOR
authFetch.interceptors.request.use(
  (request) => {
    // we can see in network tab if accept is set to 'application/json'
    request.headers.common['Accept'] = 'application/json'
    console.log('Request sent')
    return request // we always need to return the request from interceptor
  },
  (error) => {
    return Promise.reject(error)
  }
)

// RESPONSE INTERCEPTOR
authFetch.interceptors.response.use(
  (response) => {
    console.log('Response recieved')
    return response
  },
  (error) => {
    return console.log(error.response)
  }
)

export default authFetch
```

{% endcode %}

Now where this interceptors comes in handy? We can think of Authentication as one use-case.

Let's say if we get some type of response from backend, it will hit response interceptor. If the user is not logged in, then we get the 401 which can be caught in this response interceptor and we can log out the user immediately and set the state accordingly.

```javascript
// RESPONSE INTERCEPTOR
authFetch.interceptors.response.use(
  (response) => {
    console.log('Response recieved')
    return response
  },
  (error) => {
    console.log(error.response)
    // for authentication this will be 401, but since we are
    // changing url for now it is 404, but behaviour would be same
    if (error.response.status === 404) {
      // do something - we will generally update the state and may be logout the user
      console.log('Not found')
    }
    return Promise.reject(error)
  }
)
```
