1
votes

I'm building a sample web app and using this dummy data api to fetch data. I'm using React with axios to make the api call.The response data looks like following

api data looks like

So I created following interfaces to represent the data.

export type Category = {
    id: number,
    name: string
}

export type Product = {
    id: number,
    name: string,
    description: string,
    image: string,
    price: number,
    discount_amount: number,
    status: boolean,
    categories: Array<Category>
}
export type ProductResponse = {
    data: {
        code: number,
        data: Array<Product>
    }
}

I'm tying to fetch data and store in a typed state variable following way

const [products, setProducts] = useState<Array<Product>>([]);

  const fetchProducts = (): void => {
    const productUrl = "https://gorest.co.in/public-api/products";
    axios.get<ProductResponse>(productUrl).then((res) => {
      setProducts(res.data.data);
    });
  };

  useEffect(() => {
    fetchProducts();
  }, []);

There is a type error

/home/ravinda/myjunkbox/react/react-redux-cake-shop-ts/src/components/Products.tsx
TypeScript error in /home/ravinda/myjunkbox/react/react-redux-cake-shop-ts/src/components/Products.tsx(12,19):
Argument of type '{ code: number; data: Product[]; }' is not assignable to parameter of type 'SetStateAction<Product[]>'.
  Type '{ code: number; data: Product[]; }' is not assignable to type '(prevState: Product[]) => Product[]'.
    Type '{ code: number; data: Product[]; }' provides no match for the signature '(prevState: Product[]): Product[]'.  TS2345

    10 |     const productUrl = "https://gorest.co.in/public-api/products";
    11 |     axios.get<ProductResponse>(productUrl).then((res) => {
  > 12 |       setProducts(res.data.data);
       |                   ^
    13 |     });
    14 |   };
    15 |

I think I'm trying to extract the product array out of the response and set to the state variable. What am I doing wrong here?

1

1 Answers

2
votes

Based on the error given, I believe you're lacking an extra .data on your result. In order to access the value within Axios's response, you need to do a .data, in your case, .data will give you ProductResponse.

const fetchProducts = (): void => {
    const productUrl = "https://gorest.co.in/public-api/products";
    axios.get<ProductResponse>(productUrl).then((res) => {
      setProducts(res.data.data.data);
    });
  };

res.data should give you ProductResponse

res.data.data should give you

{
  code: number,
  data: Array<Product>
}

res.data.data.data should give you Array<Product>, the same type you specified in your useState.