SWR 似乎在同一个缓存键下缓存了两个不同的请求。我该如何解决?
SWR seems to cache two different requests under same cache key. How do I fix this?
我像这样使用 Axios 作为 SWR 的获取器:
// 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 };
然后我像这样获取数据:
// 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 };
在我的组件中,我有以下代码:
const { problem, isProblemLoading, mutate } = withProblem(id, {
onSuccess: (data) => {
setProblemState(data);
},
});
const { options, isOptionsLoading } = withProblemOptions(id);
现在我在控制台中看到的内容(由 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
看起来因为两个获取函数共享完全相同的 URL 响应被缓存在完全相同的键下,无论使用的请求方法是否不同。因为当我在组件中切换 withProblem 和 withProblemOptions 的顺序时,我遇到了完全相同的问题,但数据是我从 OPTIONS
请求中获得的数据,而不是像以前那样从 GET
请求中获得的数据
那么我该如何解决这个问题呢?我是否需要创建自己的缓存提供程序,它使用请求方法作为缓存键的一部分?
您可以针对每种情况使用不同的组合键,例如:
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);
我像这样使用 Axios 作为 SWR 的获取器:
// 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 };
然后我像这样获取数据:
// 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 };
在我的组件中,我有以下代码:
const { problem, isProblemLoading, mutate } = withProblem(id, {
onSuccess: (data) => {
setProblemState(data);
},
});
const { options, isOptionsLoading } = withProblemOptions(id);
现在我在控制台中看到的内容(由 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
看起来因为两个获取函数共享完全相同的 URL 响应被缓存在完全相同的键下,无论使用的请求方法是否不同。因为当我在组件中切换 withProblem 和 withProblemOptions 的顺序时,我遇到了完全相同的问题,但数据是我从 OPTIONS
请求中获得的数据,而不是像以前那样从 GET
请求中获得的数据
那么我该如何解决这个问题呢?我是否需要创建自己的缓存提供程序,它使用请求方法作为缓存键的一部分?
您可以针对每种情况使用不同的组合键,例如:
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);