Search code examples
typescriptaxiosinterfacestatereact-props

How can i pass object props and define state type?


I want to write a simple example with typescript. Using Axios to capture data from the api and print it to the screen using cards, but there is a problem with the types, when I give the state type, I encounter this error.If you do not specify the State type, there is no problem, it works normally. But when you type state, this kind of error occurs What is the problem?enter image description here I added picture of this code

import axios from 'axios'
import React, { useState, useEffect } from 'react'
import SingleCard from '../components/SingleCard'
import { SingleProduct, ListProducts } from '../config/Types'
const Home = () => {

  const [data, setData] = useState<ListProducts>([])

  useEffect(() => {
    axios.get('https://dummyjson.com/products')
      .then(res => {
        console.log(res)
        setData(res.data.products)
      })
  }, [])



  return (
    <>
      <section>
        <div className="container">
          <div className="row">
            {
              data.map((item, index) => {
                return <SingleCard product={item} />
              })
            }
          </div>
        </div>
      </section>
    </>
  )
}

export default Home


export interface SingleProduct {
    product: {
        title: string,
        description: string,
        price: number,
        thumbnail: string
    }
}

export interface ListProducts {
    data: SingleProduct[]
}



import React from 'react'
import { SingleProduct } from '../config/Types'


const SingleCard = ({ product }: SingleProduct) => {
    return (
        <>
            <div className="col-lg-3 p-3">
                <div className="card" style={{ width: '100%', height: '100%' }}>
                    <img src={product.thumbnail} className="card-img-top" alt="..." style={{ width: '100%', height: '200px', objectFit: 'cover' }} />
                    <div className="card-body">
                        <h5 className="card-title">{product.title}</h5>
                        <p className="card-text">{product.description}</p>
                        <h6>Price :{product.price} $</h6>
                    </div>
                </div>
            </div>
        </>
    )
}

export default SingleCard

Solution

  • (This answer may not related to original problem)

    Your interface usage is very confuse (and it does confuse you) to know which property store the object you want, I suggest to type the ListProducts and SingleProduct like the following:

    type ListProducts = SingleProduct[]
    
    export interface SingleProduct {
      title: string,
      description: string,
      price: number,
      thumbnail: string
    }
    

    And for SingleCard component, because react component only has one argument, you should not pass SingleProduct directly to the component. Create another interface for the component is better:

    interface SingleCardProps {
      product: SingleProduct
    }
    
    const SingleCard = ({ product }: SingleCardProps) => {
    // ...
    }