Odif Yltsaeb
Odif Yltsaeb

Reputation: 5666

SWR seems to cache two different requests under same cache key. How do I fix this?

I use Axios as fetcher for SWR like this:

// axios.js
import axios from 'axios';

// Create axios instance.
const axiosInstance = axios.create({
    baseURL: process.env.API_URL,
    withCredentials: true,
    xsrfCookieName: 'csrftoken',
    xsrfHeaderName: 'X-CSRFToken',
});

export default axiosInstance;

const fetcher = (url) => axiosInstance.get(url).then((res) => res.data);
const optionsFetcher = (url) => axiosInstance.options(url).then((res) => res.data);
export { fetcher, optionsFetcher };

And then I fetch data like this:

// withProblem.js
import useSWR from 'swr';
import { fetcher, optionsFetcher } from './axios';

const withProblemOptions = (id) => {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    const { data, error, mutate } = useSWR(`/api/sources/issues/${id}`, optionsFetcher);
    console.log('REceived optons', data);

    return {
        options: data?.actions?.PUT,
        isOptionsLoading: !error && !data,
        isError: error,
        mutate,
    };
};

const withProblem = (id, options) => {
    // eslint-disable-next-line react-hooks/rules-of-hooks
    const { data, error, mutate } = useSWR(`/api/sources/issues/${id}`, fetcher, options);
    console.log('Received problem', data);

    return {
        problem: data,
        isProblemLoading: !error && !data,
        isError: error,
        mutate,
    };
};

export { withProblemOptions, withProblem };

within my component I have the following code:

    const { problem, isProblemLoading, mutate } = withProblem(id, {
        onSuccess: (data) => {
            setProblemState(data);
        },
    });
    const { options, isOptionsLoading } = withProblemOptions(id);

Now what I see in my console (logged by the code in withProblem.js):

Received problem Object { id: 2958,  … } withProblem.js:20:12
REceived options Object { id: 2958,  … } withProblem.js:7:12
Received problem Object { id: 2958,  … } withProblem.js:20:12
REceived options Object { id: 2958,  … } withProblem.js:7:12

It looks like since the two fetcher functions share the exact same URL the response is cached under the exact same key regardless that the request method used is different. Because when I switch the order of withProblem and withProblemOptions in the component I get exact same issue, but the data is the one I get from OPTIONS request not from GET request like before

So how do I fix this? Do I need to create my own cache provider which uses the request method as a part of the cache key?

Upvotes: 1

Views: 2556

Answers (1)

Danila
Danila

Reputation: 18536

You can use different composite key for every case, for example:

const { data, error, mutate } = useSWR({url: `/api/sources/issues/${id}`, method: 'options'}, fetcher, options);

const { data, error, mutate } = useSWR({url: `/api/sources/issues/${id}`, method: 'get'}, fetcher, options);


// And the fetcher would look like that
const fetcher = ({url, method}) => axiosInstance[method](url).then((res) => res.data);

// Alternatively you an pass key as array, not object, but it's a bit less clear in my opinion 
const { data, error, mutate } = useSWR([`/api/sources/issues/${id}`, 'get'], fetcher, options);


Upvotes: 4

Related Questions