useQuery or useMutation?

What's the best way to handle side effects with React Query when making API calls in a chat application? I'm building a chat app where each API response needs to update a conversation array in state. Currently using useQuery with side effects in the queryFn, but I know this isn't ideal. Here's my current code:
const getAnswer = useQuery({
queryKey: ["getAnswer", lastConversation?.content],
queryFn: async () => {
// API call + state updates here
},
enabled: currentStage === STAGES.FINAL_ANSWER,
});
const getAnswer = useQuery({
queryKey: ["getAnswer", lastConversation?.content],
queryFn: async () => {
// API call + state updates here
},
enabled: currentStage === STAGES.FINAL_ANSWER,
});
Is useMutation a better choice here? Or should I handle state updates in a separate useEffect?
6 Replies
Rivenris
Rivenris2w ago
Personally, I'd do useQuery to fetch conversation history, and then useMutation to post new question. Within the mutation, you are free to invalidate or even override the data cached by useQuery (I'd override the cache if you don't want to pull all the data from conversation history too often). But it kinda depends on where the conversation messages are stored.
kgeek
kgeek2w ago
useQuery for GET requests useMutation from actions like: POST PUT DELETE
luis_llanes
luis_llanes2w ago
Even if they’re stored in local storage it doesn’t matter to React Query, it just needs an async function to track. I would do that too, useQuery to get the messages and every time I send a new message that’ll be a useMutation “mutate” fn and I’ll override the messages on onMutate to incluye my message before you I get a response back from the server, then onSuccess trigger an invalidation in to make the query trigger again. I believe there’s a way you can make the useQuery only take the last 2 messages that will be the one you sent (and optimistically showed on the UI via onMutation) and the one from the server. Maybe infinite query not sure, but might work That way you don’t pull the whole conversation over and over again, just the last 2 that are needed
Rivenris
Rivenris2w ago
Even if they’re stored in local storage it doesn’t matter to React Query, it just needs an async function to track.
True, although in such case I'd consider skipping useQuery entirely as there is not much benefits from using it (maybe apart from code consistency with other data sources which is actually a good reason). With indexeddb its true that you get data asynchronously, but it's such unnoticeable delay, there is pretty much no need for caching, invalidation, keys etc, so simple custom hook would be enough.
luis_llanes
luis_llanes2w ago
Oh my bad, I didn’t mean it as an actual solution for local storage, I was just trying to say that as long as you pass an async function to React Query it doesn’t care what it is
BadBoy
BadBoyOP5d ago
We are not storing conversation history as of now, so its just one-way traffic right now. We are kind of using POST for everything; not optimal ik but that's what the backend guys have done. So, the above rule might not work in this case.

Did you find this page helpful?