Not sure what's going on, but I just realized that the isValidating flag returned from useSWR often gets stuck on true when cancelling a request.
I've managed to boil it down to the following example:
import React, { useState, useCallback } from 'react';
import useSWR from 'swr';
function Test() {
const [input, setInput] = useState('');
const handleChange = useCallback(e => setInput(e.currentTarget.value), [setInput]);
const handleClear = useCallback(() => setInput(''), [setInput]);
const { data, isValidating } = useSWR(
input ? `https://jsonplaceholder.typicode.com/posts/${input}` : null,
async key => {
// NOTE: This is just to make a slow request. It happens with actual slow requests too.
await new Promise(resolve => setTimeout(resolve, 2000));
const res = await fetch(key);
return res.json();
}
);
return (
<>
<form>
<input value={input} onChange={handleChange} />
<button type="button" onClick={handleClear}>
Clear
</button>
</form>
<output>
{isValidating
? 'Validating...'
: JSON.stringify(data, undefined, 2) || typeof data}
</output>
</>
);
}
isValidating will change to true.isValidating is still true, either by just backspacing until empty, by clicking the button, then isValidating _never_ returns to false.isValidating returns to true when the new request finishes.isValidating will remain false as expected.What's going on? 馃槙
The isValidating value currently is not strongly bound to the key like data does. Will get this fixed in the next version.
@Svish does this work out for your issue?
-{!isValidating
+{(!data && isValidating)
? 'Validating...'
: JSON.stringify(data, undefined, 2) || typeof data}
only display the "Validating" text when there's no data fallback from cache and meanwhile swr is doing the revalidation. when you backspace, swr will do soft revalidate to refetch the state for that key so the isValidating is set to true again.
The isValidating value currently is not strongly bound to the key like data does. Will get this fixed in the next version.
another note for shuding's comment, swr binds isValidating with key after v0.3.3 already. not seems it won't solve your problem.
@huozhi Potential workaround, perhaps. Either way, I believe this seems to me to be a bug that should be fixed, rather than worked around.
Still on version 0.2.2 because of this, and haven't really bothered trying to upgrade until this is confirmed fixed. Also on a different project at the moment, so can't check right now, unfortunately.
For a key that has state been resolved before, swr will try to refetch the latest state to make sure it's matching the result fetcher gets from remote. I would say it's not really a bug behavior.
I feel your scenario is more like: I want the fetcher do nothing if the state is resolved once?
so the solution could be either (1) check if the data is resolved already in fetcher, and decide whether to send another request.
or (2) use the condition like !data && isValidating stuff to determine it's fetched when render.
(1) can be considerred as a feature quest, giving more information in fetcher that could let user decide when to fetch.
Not sure I follow you, but either way, the issue here was never what swr was doing with revalidating or refetching or using cached values or whatever. It is that isValidating in a certain scenario gets stuck on true, even though there actually is no validation happening anywhere.
That's an issue, because one of the main points of the isValidating flag (in my opinion) is to be able to show a status to the user that something is happening. And when that gets stuck on true, you end up with a constant spinner shown to the user, without anything actually happening, which is both confusing and wrong. isValidating should _always_, at some point, return to false. And in the version after 0.2.2, it stopped doing that. And every version I tested after that, it still wasn't. Up till maybe 6 months ago or something, where I had to switch project (one not using swr) and stopped testing.
That's the bug part that I want fixed.
Most helpful comment
The
isValidatingvalue currently is not strongly bound to the key likedatadoes. Will get this fixed in the next version.