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.
import { clearCache } from "swr";
clearCache(); // clear all cache
clearCache("/api/data"); // clear only a certain cache key
鈽濓笍 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.
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 cache object directly?
Another thing I've been thinking is #92, which will only remove the inactive keys.
If we clear/change the cache of an active SWR hook, it might cause some unexpected behavior.
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.
For example, with a simple component that fetches data:
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.
The only way to test this behavior is to change the id propr, but it's not always feasible, depending on the test scenario.
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.
Awesome!
@quietshu something is weird here. When testing, my second test stills renders with the result provided by a previous test.
I tried a cache.clear() in a beforeEach and before rendering the component within the test, both fails.
If I run each test at a time they pass.
@andreoav check my answer here https://github.com/zeit/swr/pull/231#issuecomment-591614747
@sergiodxa
I am using a similar idea on my SWR vue library. In fact, i find this statement wrong:
I agree that cleaning the cache it's not something you should want in production, I only need it for testing purposes.
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:
import { cache } from "swr"
cache.clear()
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.
Most helpful comment
Agree to expose a way to clear the cache, it's a common scenario.
For example, with a simple component that fetches data:
The second expectation fails, 'cause SWR dedupes the requests, returning the first result from the cache.
The only way to test this behavior is to change the
idpropr, but it's not always feasible, depending on the test scenario.