mike castro
mike castro

Reputation: 17

React API single Product not rendering

I am able to get all products to show when mapping from API, but when I try to get a single item to show, I get nothing displayed. When I look at the network tag in dev tools, it shows the specific item was successfully requested, but nothing renders.

(The main screen that maps everything works fine)

import React, { useState, useEffect } from 'react'
import Product from '../components/Product'
import { Row, Col } from 'react-bootstrap'
import axios from 'axios'

const HomeScreen = () => {
    const [products, setProducts] = useState([])

    useEffect(() => {
        const fecthProducts = async () => {
            const { data } = await axios.get('/api/products')

            setProducts(data)
        }

        fecthProducts()
    }, [])

    return (
        <>
            <h1>Jewelry</h1>
            <Row>
                {products.map((product) => (
                    <Col key={product.id} sm={12} md={6} lg={4} xl={3}>
                        <Product product={product} />
                    </Col>
                ))}
            </Row>
        </>
    )
}

export default HomeScreen

(this is the single product page where)

import { Link, useParams } from 'react-router-dom'
import {
    Row,
    Col,
    Image,
    ListGroup,
    ListGroupItem,
    Button
} from 'react-bootstrap'
import axios from 'axios'

const ProductScreen = () => {
    const [product, setProduct] = useState([])
    const { id } = useParams()

    useEffect(() => {
        const fetchProduct = async () => {
            const { data } = await axios.get(`/api/products/${id}`)

            setProduct(data)
        }

        fetchProduct()
    }, [id])

    return (
        <>
            <Link className="btn btn-light my-3" to="/">
                GO BACK
            </Link>

            <Row>
                <Col md={4}>
                    <div>
                        <Image src={product.image} alt={product.name} fluid rounded />
                    </div>
                </Col>
                <Col md={3}>
                    <ListGroup>
                        <ListGroupItem>
                            <h4>{product.name}</h4>
                            <h5>${product.price}</h5>
                        </ListGroupItem>
                        <ListGroupItem>{product.description}</ListGroupItem>
                        <ListGroupItem>
                            {product.inStock > 0 ? 'In Stock' : 'Out of Stock'}
                        </ListGroupItem>
                        <ListGroupItem>
                            <Button
                                className="btn-block"
                                type="button"
                                disabled={product.inStock === 0}
                            >
                                Add to Cart
                            </Button>
                        </ListGroupItem>
                    </ListGroup>
                </Col>
            </Row>
        </>
    )
}

export default ProductScreen

The picture below shows how the ProductScreen page renders

https://i.sstatic.net/PJKpa.png

Upvotes: 1

Views: 147

Answers (2)

Nokwiw
Nokwiw

Reputation: 396

product in your case is an aray of one element, use the code below instead :

useEffect(() => {
    const fetchProduct = async () => {
        const { data } = await axios.get(`/api/products/${id}`)

        setProduct(data[0])
    }

    fetchProduct()
}, [id])

Upvotes: 0

Mohsin Baig
Mohsin Baig

Reputation: 87

In product state, you are storing the Array of objects not a single object please get the result something like in render function

product && product[0] && product[0].name

and same like other values change according to the properties.

Upvotes: 1

Related Questions