Web Dev Cody
Web Dev Cody5mo ago

Question about Error

I have a page in react which does a useQuery(api.stories.getStory), and I also have a button on that page which deletes that story resource. I'm seeing an issue where after I delete the resource, I have logic to redirect back to another page, but the useQuery seems to fire before the redirect finished and causes the app to throw an error.
Does anyone have a pattern I can use to prevent this type of issue? The only approach I know of it to never have queries throw errors, and instead just have them return null or undefined or something
5 Replies
Web Dev Cody
Web Dev CodyOP5mo ago
I'm already wrapping the component with a ErrorBoundary, but it still seems to stop the redirect
ballingt
ballingt5mo ago
What's the logic precisely? The Convex client will ensure that the useQuery hooks fire before the mutation promise resolves, which it sounds like would cause this. We've talked about separately exposing a callback for "this mutation has finished," which would generally be before the useQuery hooks run. Re wrapping the component in an errorboundary stopping the redirect, I'd be interested to see this logic
Web Dev Cody
Web Dev CodyOP5mo ago
@ballingt the logic was this - user navigates to a page which has a useQuery on it, that query throws an error if the record was not found - record was found, because it exists, returned in the query - on that same page, a user clicks a button to delete the resources by running a mutation (it also tried to redirect after successfully deleting the record) - the mutation runs, but then the query updates and catches that error - the app break I've run into multiple times and honestly I can't figure out how to get around it short of making sure my queries never throw errors... which maybe that's just "the way" it should be done, but idk if that's called out in the docs this is all a next app btw I do think an addition to the sdk might solve my issue, but you'd still have to make sure the router.push fully finishes inside of next.js before the query re-runs and crashes the app. wrapping the component which runs the useQuery in an error boundary is not a very good DX either imo because it often requires you to extract your useQuery into yet another component so that you can wrap in an error boundary
function MyComponent() {
const deleteRecord = useMutation(api.record.delete, {
onSuccess() {
router.push('/my/new/path')
},
onError(error) {
toast.error(error)
}
})

return <button onClick={deleteRecord} />
}
function MyComponent() {
const deleteRecord = useMutation(api.record.delete, {
onSuccess() {
router.push('/my/new/path')
},
onError(error) {
toast.error(error)
}
})

return <button onClick={deleteRecord} />
}
Michal Srb
Michal Srb5mo ago
I think another option is to use a useQuery that doesn't throw but returns the error. convex-helpers have one such variant, and Tanstack Query is another option. I would probably not throw as the most straightforward solution. Since the record is deletable, I'd consider handling the deleted scenario as something the query should always do. Relying on the client never subscribing to the query in that state seems more fragile.

Did you find this page helpful?