skip to Main Content

I want to display the products after fetching them and everything works fine but I have some error with TS in the destructuring statement.

Here is my fetching function:

export async function fetchAllProducts() {
  try {
    const res = await axios.get(url);
    const data = res.data;
    return {
      data
    }
  } catch(err) {
    if(err instanceof AxiosError)
      return {
        error: err.message
      }
  }
}

And then I use it in a server component:

export default async function StorePage() {
 const { data, error }: Products = await fetchAllProducts(); //the problem is in this line (data and error are underlined) 
  
  return (
    <section className='section'>
      <div className='section__inner'>
        <h4 className='section__title'>Products</h4>
        {error && <span>{error}</span>}
        {!data && !error && <span>loading...</span>}
        <div className='section__content products-container'>
          {!error && data && data?.length > 0 && data.map((product: ProductProps) => <ProductCard key = {product.id}  {...product}/>)}
        </div>
      </div>
    </section>
  )
}

When I destructure I get this error:

Type ‘{ data: any; error?: undefined; } | { error: string; data?:
undefined; } | undefined’ is not assignable to type ‘Products’. Type
‘undefined’ is not assignable to type ‘Products’.

Here are my types:

export type Products = {
  data: ProductProps[] | null;
  error: string | undefined;
}


export type ProductProps = {
  id: string;
  title: string;
  category: string;
  description: string;
  image: string;
  price: number;
  rating: {
    rate: number,
    count: number
  }
}

So, I was wondering if the problem was connected to the fetch function, should I add types there or is there another issue?

2

Answers


  1. The issue is with your catch function, since if if(err instanceof AxiosError) condition does not fulfill, fetchAllProducts function will return undefined.

    You should add a fallback {} return.

    Typescript demo

    catch(err) {
      if (err instanceof AxiosError) {
        return {
          error: err.message,
        };
      }
    
      return {
         error: 'fallback error',
      };
    }
    
    Login or Signup to reply.
  2. In

    export type Products = {
        data: ProductProps[] | null;
        error: string | undefined;
    }
    

    the data property has either to be a ProductProps[] or null. But in case of an error during fetchAllProducts

     const { data, error }: Products = await fetchAllProducts(); 
    

    the result of fetchAllProducts will be

    {
       error: string
    }
    

    ie, no data, ie data == undefined which is not allowed in a valid instance of the Products type … Change the return value in case of an exception to

    return {
      error: err.message,
      data: null
    }
    

    Also in your Products, the error is a mandatory property, ie it can have the value of undefined but it has to exist. If you want it to be optional, define your Products as follows

    export type Products = {
      data: ProductProps[] | null;
      error?: string;
    }
    

    See this Playground to see the difference.

    Furthermore, you should also consider, what happens if err is not an AxiosError. Then your fetchAllProducts won’t return anything and you will try to destructure a value of undefined, which will throw a runtime error.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search