59

I am trying to query a quote API for a freeCodeCamp project I'm updating to React.js. I am now trying to use Fetch or Axios to query the API but it's caching the response in the browser. I know in $ajax there is a { cache: false } that would force the browser to do a new request.

Is there some way I will be able to do the same with Fetch or Axios?

The cache-control setting seems to be already set to max-age: 0 by Axios.

enter image description here

This is my code I have that is querying the API.

generateQuote = () => {
  axios.get('https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1')
    .then(response => {
      const { title, content, link } = response.data[0];
      console.log(title, content, link)
      this.setState(() => ({ title, content, link }));
    })
    .catch(err => {
      console.log(`${err} whilst contacting the quote API.`)
    })

}

2
  • 8
    Have you tried 'Cache-Control': 'no-cache' in axios settings? Commented Mar 13, 2018 at 18:47
  • 1
    Yup. That specific API starts giving a error about no Cache-Control found pre-flight. It seems I can't set that header like that with that specific API Commented Mar 13, 2018 at 19:34

6 Answers 6

76

Okay so I found a solution. I had to set a timestamp on the API url to get it to make a new call. There doesn't seem to be a way to force axios or fetch to disable cache.

This is how my code now looks

axios.get(`https://quotesondesign.com/wp-json/posts?filter[orderby]=rand&filter[posts_per_page]=1&timestamp=${new Date().getTime()}`)
  .then(response => {
    const { title, content, link } = response.data[0];
    console.log(title, content, link)
    this.setState(() => ({ title, content, link }));
  })
  .catch(err => {
    console.log(`${err} whilst contacting the quote API.`)
  })
Sign up to request clarification or add additional context in comments.

5 Comments

With axios 0.18.0 the request was always sent if the response had the Cache-Control: no-cache header set.
This was happening for me on IE 11 (using Outlook Addin). This solution worked like a charm.
This worked for me. I added a timestamp param to all get requests from the request interceptor and it didn't seem to cause any issues with anything else. Thanks.
adding timestamp in request url is treated as another new url. Does axios store this data as cache for each url?
Adding an additional parameter may not be always possible, the API could refuse to answer... Also this solution is not 100% guaranteed to always use a different timestamp value (race conditions), maybe also add a random value to the URL additionally
48

I added these headers to all axios requests and it's working well.

axiosInstance.defaults.headers = {
  'Cache-Control': 'no-cache',
  'Pragma': 'no-cache',
  'Expires': '0',
};

2 Comments

The Pragma: no-cache is required for iOS Safari to behave correctly, see bugs.webkit.org/show_bug.cgi?id=170714
This results in an error with this message: Request header field cache-control is not allowed by Access-Control-Allow-Headers in preflight response.
26

If you do not want to disable caching for all axios requests, you can disable caching for only one request by using the following parameters in the axios call:

axios.get(
  'https://YOUR-URL.com',
  {
    // query URL without using browser cache
    headers: {
      'Cache-Control': 'no-cache',
      'Pragma': 'no-cache',
      'Expires': '0',
    },
  }
)

1 Comment

this is never reliable. I have seen so many proxies and routers and firewall ignoring all the headers and continuing responding with cached data. the only reliable method is a random number in query string
5

It seems, adding timestamp is the only always working way.

If you're using Vue, for example:

const api = axios.create({
  baseURL: 'https://example.com/api',
  params: {
    t: new Date().getTime()
  }
})
Vue.prototype.$api = api

So you can use it with:

this.$api.get('items')

And it will always add different timestamp to the url, depending on current request time.

Comments

3

I think you just need to make the url different each time you make the axios call. Timestamp is just one way to do so. Also consider disabling or filtering service workers caching method if you are developing a PWA.

2 Comments

If you check the screenshot you will see there is no service worker file being downloaded, because I wasn't using a service worker to create a PWA.
Al Herrera, does adding the timestamp also prevent a service worker from catching?
2

Create an instance of axios and then add timestamp to every request.

const axiosInstance = axios.create({})

axiosInstance.interceptors.request.use(
    function (config) {
      // Do something before request is sent
      config.params = { ...config.params, timestamp: Date.now() };
      return config;
    },
    function (error) {
      // Do something with request error
      return Promise.reject(error);
    }
  );

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.