New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
useAsyncFn - return Promise.reject() or Promise.resolve() in the promise resolution #612
Conversation
I think you want to do the following: const [{value: register, loading, error}, handleRegisterSubmit] = useAsyncFn(
() => Service.register(payload),
[payload]
) That said, I'm not entirely clear on why the callback returns the value or error in the first place... |
@wardoost because, as i remember, if value returned from |
@wardoost what you suggested above gave me the same result, can't reach the |
I see what you mean now. I would have implemented your example like this as I would want the state represent how the async function resolved or failed: const [{value, loading, error}, handleSubmit] = useAsyncFn(
async () => {
try {
const result = await Service.register(payload)
// handle result
} catch (error) {
// handle error
}
},
[payload]
) I can see there are use cases where you want the returned state of this hook to only represent part of some async function or handle failure differently with separate state. Your change seems to do this well but an error is show in the console when not catching errors which this hook is intended to do. I would recommend using this hook as I show above. |
@wardoost I see you grasped the idea, and the way you've shown above solves the problem if I only call I've changed Now it won't complain about not handling error thrown on |
9993476
to
32b0020
Compare
@diegoarcega This only solves the the problem of uncatched errors in As you've mentioned my snippet above solves most use cases. The problem you're trying to solve seems to be the edge case which could be solved by checking if the awaited result is an error. If it is an error object you decide what to do with it, which can be handled differently in different places. |
I understand that with useAsync one wouldn't want to handle errors in the callback, because this is only called once on component mount, no need to manually call the callback. However, with useAsyncFn an error can occur at any point while interacting with the app and the developer will want to not only show a message when the useAsyncFn returns an error, but also maybe make another request to the server or any other non UI related action. Moreover, I wouldn't say catching an error after a failed promise is an edge case, it is more of a normal routine in software development. If an error occurs, I would expect the app to have a handler for that. Checking for error in the success response doesn't seem like how standard apis should be made, more like a workaround imo. One of the reasons why one would use a useasyncfn hook is its reusability but if the dev wants to reuse the callback in just one more place, it won't work, a new callback needs to be created but then you will be repeating the creation of the callback just because you are using it in another place and the hook doesnt support that. I see that useAsyncFn was designed to handle simpler cases and it is not the idea of this hook to implement what I said above. I will have to create another hook with the features I want. Thanks @wardoost |
@diegoarcega Catching an error after a failed promise is definitely not an edge case.. That's why errors are catched in all async hooks in this library and expressed in an object with You can reuse the callback in different places in your components but if a promise handles errors differently, and maybe fire off a second network request when that happens, it is not the same callback.
I definitely agree on this hence why I said the following in my first comment:
In my opinion the callback shouldn't return anything as to not confuse devs. It looks like it was put there as an escape hatch to do things you are trying to do. |
Why not throw the error ? |
I can't catch the error... I must check if the response is instance of Error... sad |
Guys, I had the same problem and the quick workaround form me was introducing a new hook in my project to replace import React from 'react'
import { useAsyncFn as useAsyncFnOriginal } from 'react-use'
export const useAsyncFn = (...args: Parameters<typeof useAsyncFnOriginal>): ReturnType<typeof useAsyncFnOriginal> => {
const [state, callback] = useAsyncFnOriginal(...args)
const callbackEnhanced = React.useCallback(async (...cbArgs: Parameters<typeof callback>) => {
const result = await callback(...cbArgs)
if(result instanceof Error) throw result
return result
}, [callback])
return [state, callbackEnhanced]
} But will it only work when the promise will reject with an error! |
Problem