-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Have a way to clear cache #161
Comments
For testing purposes what I made to solve this is to ensure I'm always using different keys, since they are based on a prop, but still would be nice the be able to do: import { clearCache } from "swr";
afterEach(() => clearCache); And ensure all my tests have zero cached data. |
What do you think about the idea of exporting the |
Another thing I've been thinking is #92, which will only remove the inactive keys. |
So far I haven't needed, until now, direct access to the internal cache, with it I could have done what I needed creating the clearCache function myself. I agree that cleaning the cache it's not something you should want in production, I only need it for testing purposes. Does SWR listen to cache changes? Maybe this way if an active SWR hook is using a cleared key it could automatically trigger a new fetch as if it was new? 🤔 This way if you still have a rendered component using the cleared key it wouldn't break, just change to loading state as if it was a new key? Just thinking out loud. |
Agree to expose a way to clear the cache, it's a common scenario. it('should fetch on mount', async () => {
await act(async () => {
<Foo id="1" />
});
expect(fetch).toHaveBeenCalledWith('1');
});
it('should show an error when fetch fails', async () => {
(fetch as jest.Mock).mockRejectedValue(new Error('An error occured'));
await act(async () => {
mount(
<Foo id="1" />
);
});
expect(fetch).toHaveBeenCalledWith('1');
// other assertions that the error message is rendered
}); The second expectation fails, 'cause SWR dedupes the requests, returning the first result from the cache. |
I'm having problems with SWR and jest tests. It fails when a test has a swr call that was used in a previous test.
|
Fixes vercel#161 by simply exposing an existing function. I added my tests to the end of the use-swr.test.tsx file because the file wasn't long enough.
Awesome! |
@quietshu something is weird here. When testing, my second test stills renders with the result provided by a previous test. I tried a If I run each test at a time they pass. |
@andreoav check my answer here #231 (comment) |
I am using a similar idea on my SWR vue library. In fact, i find this statement wrong:
I've written some applications where the cache TTL is about 1 minute. So, if I visit the dashboard and it fetches some data with a TTL 1 min, then logout and login with another user (with less than a minute apart) then that cache still shows the old user values and does not revalidate yet due TTL < 1 min. The quickest solution is to delete all cached keys or the ones specified at logout, this ensures fresh data upon login. This is the clear function I did: https://github.com/ConsoleTVs/vswr/blob/6a84e923d9db31784316b975f98db1f5eaea3140/src/swr.ts#L219 |
@ConsoleTVs what i usually do is to reload the page in a logout so cache is cleared, also most users don't login, see data, logout and see new data in less than 1 minutes IMO. However, with the current cache you can do it with cache.clear() if you don't reload on logout. |
Just keep in mind, that the (mobile) application we're building probably have a safe cache of Infinity, since we know exactly when we need to reload / mutate it via events, 1 min was just for testing :) Nevertheless, is it possible with cache.clear() on react's SWR? How do you access the cache instance then? |
You can import the cache and clear it with:
This has been available since #231 was merged |
Is this actually documented on the docs page? Very interesting indeed |
It's not documented yet |
Ha! Been looking for this, can someone please document this, very important feature. |
@sergiodxa Page reload is not possible in a React Native app. 😀 I was surprised the documentation didn't cover this. I would have expected it to be at the bottom of the Mutation page which deals with cache updates anyway. This also simplifies handling authentication, as you can just clear the cache every time authentication changes. In this case the fetcher method can obtain access tokens itself instead of passing them in the key every time (see #325 (comment)). |
This seems to have been updated at some point, but couldn't find the exact commit or PR when. I was able to create a new cache on each test with this: import { SWRConfig } 'swr';
<SWRConfig value={{ provider: () => new Map() }}>
{/* SWRConfig is given a new provider on each test so that it's caching is emptied between each test */}
{children} {/* or the component you want to test that uses `useSWR` */}
</SWRConfig> https://swr.vercel.app/docs/advanced/cache#reset-cache-between-test-cases |
But then you have to wrap new config per test, instead of just using one. I also used the cache.clear() undocumented feature and found out its gone now :( It was super helpful for tests |
What version of |
Doesn't seem like the Also, for those of you who want use const wrapper = ({ children }) => <SWRConfig value={{ provider: () => new Map() }}>{children}</SWRConfig>
test('test something', () => {
// provide a "clean" wrapper for `swr`
const { result } = renderHook(useFetchWithSWR, { wrapper })
// etc...
}) |
@andersnylund method of using a wrapper with a cache provider is the way to do this as of 1.0.0 per the docs: https://swr.vercel.app/docs/advanced/cache#reset-cache-between-test-cases |
@JamieKudla they literally list a clear method at the end of thst page, is that not working? |
There is no function defined to delete all caches. Is the documentation wrong? |
@andersnylund comment (#161 (comment)) looks to do the trick, same solution for Storybook using a decorator: import React from 'react';
import {
DecoratorFn,
} from '@storybook/react';
import {
SWRConfig,
} from 'swr'
export const StoryDecorator: DecoratorFn = (Story: any, {}) => {
return (
<SWRConfig value={{ provider: () => new Map() }}>
<Story />
</SWRConfig>
);
};
export default null; |
@Ajido import "swr/dist/types";
declare module "swr/dist/types" {
export interface Cache {
clear(): void;
}
} |
The Cache has been exposed since [1], which supposedly includes a .clear() method [2], which in turn is not actually present in the type definition [3]. This adds it to the type definition to align with the implementation. Since Map also contains a .clear() method [4], this shouldn't break the ability to pass that in as a map. [1] vercel#231 [2] vercel#161 (comment) [3] vercel#161 (comment) [4] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear
This is super awkward to implement. Would love a clear way to clear cache for all tests. |
Please checkout #1887 (comment) for the new cache clear approach introduced in v2 beta |
I'm writing tests for a component using
useSWR
, also with{ suspense: true }
, and if I render a component reading the same key (e.g. the same component with different keys) I'm getting the old cache in my second test.Not sure if this will be addressed with #158, but having a way to tell SWR to clear the cache of a certain key would be awesome for this use case.
☝️ something like that.
What I have tried:
mutate(key, null, false)
mutate(key, {}, false)
Both doesn't work right since useSWR will still read that
null
or{}
from the cache instead of triggering an immediate fetch and suspending the component.I will try to create a CodeSandbox to replicate this soon.
The text was updated successfully, but these errors were encountered: