Download button: query or mutation?
Our application has several "Download" buttons for fetching various PDFs or CSVs from the server. Since these are idempotent
GET requests, my inclination is to use useQuery — but because it can be a lot of data, we don't want to fetch immediately on page load.
I haven't found any guidance either here, in the docs, in Github, or on Stack Overflow on which is the recommended mechanism:
Option 1: useQuery
A useQuery with enabled set to false, then using query.refetch() in our click handler. This used to be paired with an onSuccess callback to trigger a file save, but now has moved to a useEffect.
This code looks approximately like:
Option 2: useMutation
This seems more straightforward to implement, though is a bit incongruous with my mental model of when to use a mutation.
Rough code:
14 Replies
xenophobic-harlequin•3y ago
You can also combine these approaches. useQuery to make good use of the cache and then a mutation that calls queryClient.ensureQueryData of that query. This has a nice onSuccess 🙂
dependent-tanOP•3y ago
Honestly that sounds more complicated. Wondering if @TkDodo 🔮 has a recommended best practice on this.
rare-sapphire•3y ago
FYI, we use solution 1 on our side for the same pattern. In addition we had
cacheTime: 0 so that we do not keep the file content in the cache. RQ is used "only" to have accurate loading/error state.xenophobic-harlequin•3y ago
Then a mutation would be a better fit…
rare-sapphire•3y ago
Hum, what bothers me is that "mutation" means "change" in my head, which is not the case here.
stormy-gold•3y ago
does the server create the PDF on the fly? If so I would say its a mutation
dependent-tanOP•3y ago
It depends on what’s being downloaded, but I think that’s a reasonable heuristic.
rare-sapphire•3y ago
In our case nothing is generating. It is a file loading query to retrieve the content of the file in memory. Not « really » a mutation 😁
But it is triggered by a click on a button so not really a « query » neither
correct-apricot•3y ago
Is the native anchor download attribute an option?
dependent-tanOP•3y ago
Not really — we're fetching from an API that expects auth headers. We could feasibly work to change the API to accept some sort of token-based authentication param on the download endpoints.
Based on this thread and the conversation with our team, I think we're likely to go with the simplest implementation which is
useMutation. I agree with @glabat that "mutation" means "changes something on the server" in my head, but is maybe more realistically though of as "network interaction as the result of user action"exotic-emerald•3y ago
Do you know you can still use plain old fetch request to download a file? My point is simple if you don't need the data to be stored in the cache, don't use RQ for it. I also had a temptation to put everything in RQ since I used it, but after reasoning about it I came to the conclusion that's not the case. Downloading files is a utility functionality thus it should be on a low level, a simple request.
rare-sapphire•3y ago
RQ helps with loading and error states
exotic-emerald•3y ago
If that's all you need you can write it in a few lines of code. As for me, it's overhead to use RQ just for the sake of loading state and error handling
rare-sapphire•3y ago
It depends as usual 😅. In our case it is more consistent with our code base. But I agree that it may add overhead in other cases.