Skip to content
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

Problems to make it work with TypeScript and axios #31

Closed
svschannak opened this Issue Mar 13, 2019 · 11 comments

Comments

Projects
None yet
2 participants
@svschannak
Copy link

commented Mar 13, 2019

I am trying to use react-async in an app with TypeScript and Axios, but can't find any documentation about it, would be great to find som, because they are pretty popular. If you can help me with my problem i would be happy to create a PR or write an article about it, because i really like the idea of your package.

My basic problem is that i have a function that handles the fetch via axios with async/await:

    const fetchCategories = async() => {
        const response = await axios.get("/route/");
        return response;
    }

And in my Component i use the following:

<Async promiseFn={fetchCategories}>...</Async>

Now, TS throws the following error:

JSX element type 'Async<AxiosResponse<any>>' is not a constructor function for JSX elements.
  Type 'Async<AxiosResponse<any>>' is missing the following properties from type 'Element': type, key

But i don't really understand what is going on here - what kind of response does promiseFN expect, because 'Element': type, key seems to be very generic. Or did i understand something fundamentally wrong?

@svschannak

This comment has been minimized.

Copy link
Author

commented Mar 13, 2019

I actually got it working, when i started to use useAsync.

But it is failing, when I want to pass custom props like this:

const fetchCatalogData = async (props:any) => {
    const response = await api.get(`${apiRoutes.catalog}/${props.catalogId}/`);
    return response.data;
}
const { data, error, isLoading } = useAsync({ promiseFn: fetchCatalogData, catalogId: 1 });

The reason for this is that the type definitions won't accept any custom parameters. I mean it can, if you declare your interface as any. But this would work against the advantages of TypeScript. What I actually did was changing the interface of AsyncOptions to the following code:

interface AsyncOptions<T> {
  promise?: Promise<T>
  promiseFn?: (props: object, controller: AbortController) => Promise<T>
  deferFn?: (args: any[], props: object, controller: AbortController) => Promise<T>
  watch?: any
  watchFn?: (props: object, prevProps: object) => any
  initialValue?: T
  onResolve?: (data: T) => void
  onReject?: (error: Error) => void
  parameters?: object
}

As you can see, i added the parameters type to pass extra parameters to the Promise function and it actually works. Is there any other way to do this with TypeScript or should I create an PR for this?

@ghengeveld

This comment has been minimized.

Copy link
Owner

commented Mar 14, 2019

Both <Async> and useAsync() should be able to work with Axios and async/await. TypeScript seems to be complaining about the properties that <Async> exposes. Could you maybe create a CodeSandbox that reproduces the error?

It's not really a surprise that useAsync "fixes" the error, because it doesn't create an Element at all. As for the type signature for additional props, it seems you're suggesting the addition of a parameters prop/option, correct? That would mean an API change that offers an alternative way to pass additional props. I prefer to keep the API the way it is, and instead update the TS typings to be compatible with the existing API. I think we can achieve this using an indexer:

interface AsyncOptions<T> {
  promise?: Promise<T>
  promiseFn?: (props: object, controller: AbortController) => Promise<T>
  deferFn?: (args: any[], props: object, controller: AbortController) => Promise<T>
  watch?: any
  watchFn?: (props: object, prevProps: object) => any
  initialValue?: T
  onResolve?: (data: T) => void
  onReject?: (error: Error) => void
  [prop: string]: any
}

Note the last statement, which specifies an indexer. Will that work for you?

@svschannak

This comment has been minimized.

Copy link
Author

commented Mar 14, 2019

Yes, that works pretty well and it won't affect any current code.

@ghengeveld

This comment has been minimized.

Copy link
Owner

commented Mar 14, 2019

Cool. Published in v5.1.1.

@ghengeveld ghengeveld closed this Mar 14, 2019

@ghengeveld

This comment has been minimized.

Copy link
Owner

commented Mar 14, 2019

Thanks for reporting!

@svschannak

This comment has been minimized.

Copy link
Author

commented Mar 15, 2019

I just leave my blog entry about this here if somebody else wants to get it work with TypeScript: https://www.schannak.com/posts/react-async-typescript/

@ghengeveld

This comment has been minimized.

Copy link
Owner

commented Mar 16, 2019

Awesome! Care to link to https://react-async.dev from the article? I'm trying to get React Async higher up in Google 😇

@svschannak

This comment has been minimized.

Copy link
Author

commented Mar 18, 2019

Done ;).

@ghengeveld

This comment has been minimized.

Copy link
Owner

commented Mar 27, 2019

Hey @svschannak I just created a pre-release for #37 which greatly improves usability with TypeScript. You can install it as react-async@6.0.0-0 or react-async@next. It will soon be released, but I'd like to gather some feedback first. Care to take a look and try it out?

@svschannak

This comment has been minimized.

Copy link
Author

commented Apr 1, 2019

@ghengeveld I will try it out. But I think you have already released it, right?

@ghengeveld

This comment has been minimized.

Copy link
Owner

commented Apr 1, 2019

Yes, it's released now. You can just use react-async@latest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.