How to define useAsync (react-async-hook) with TypeScript?

1.6k views Asked by At

I am using react-async-hook for fetching API data in React component.

const popularProducts = useAsync(fetchPopularProducts, []);

fetchPopularProducts() is asynchronous method for making api call using fetch:

export async function fetchPopularProducts(
limit = 10,
start = 1
): Promise<Response<PopularProduct[]>> {
  const apiUrl = `${API_BASE_URL}/rest/V1/fastlaneapi/product/popular? limit=${limit}&start=${start}`;
const res = await fetch(apiUrl);
const json = await res.json();

if (res.status !== 200) {
  const message = json.message !== undefined ? json.message : "";
  throw new RequestError(message, res.status);
}

  return json;
}

How to define with TypeScript, response of useAsync hook, I tried like this below but it's not working:

  const popularProducts = useAsync<AsyncState<Response<PopularProduct[]>>> 
  (fetchPopularProducts, []);

AsyncState type is from react-async-hook library and it looks like this

export declare type AsyncState<R> = {
  status: AsyncStateStatus;
  loading: boolean;
  error: Error | undefined;
  result: R | undefined;
};

So instead of "R", I tried to provide my result from fetchPopularProducts() method which is: Response<PopularProduct[]>, but it's not working.

Error message:

TS2769: No overload matches this call.
   Overload 1 of 2, '(asyncFunction: () => Promise<AsyncState<Response<PopularProduct[]>>>, params: UnknownArgs, options?: Partial<...>): UseAsyncReturn<...>', gave the following error.
     Argument of type '(limit?: number, start?: number) => Promise<Response<PopularProduct[]>>' is not assignable to parameter of type '() => Promise<AsyncState<Response<PopularProduct[]>>>'.
       Type 'Promise<Response<PopularProduct[]>>' is not assignable to type 'Promise<AsyncState<Response<PopularProduct[]>>>'.
         Type 'Response<PopularProduct[]>' is missing the following properties from type 'AsyncState<Response<PopularProduct[]>>': status, loading, error, result
   Overload 2 of 2, '(asyncFunction: (...args: UnknownArgs) => Promise<AsyncState<Response<PopularProduct[]>>>, params: UnknownArgs, options?: Partial<...>): UseAsyncReturn<...>', gave the following error.
     Argument of type '(limit?: number, start?: number) => Promise<Response<PopularProduct[]>>' is not assignable to parameter of type '(...args: UnknownArgs) => Promise<AsyncState<Response<PopularProduct[]>>>'.
       Type 'Promise<Response<PopularProduct[]>>' is not assignable to type 'Promise<AsyncState<Response<PopularProduct[]>>>'.
1

There are 1 answers

0
PaulMest On

I had this problem for a couple of days and this is what worked for me

  1. Use the PromiseFn type from react-async itself
  2. Use an Object for the arguments to the async function instead of positional arguments

Example

Calling Function with 1 parameter

const { data, error, isPending } = useAsync({
  promiseFn: getActiveSolution,
  slug: '2022-08-04',
});

Defining the function with 1 parameter

import { useAsync, PromiseFn } from 'react-async';

export const getActiveSolution: PromiseFn<Object> = async ({ slug }) => {
  ...
}