Reputation:
I am pulling data from an internal API that returns an image that I am trying to display. I have a page function that is set to display the information from that response. The response is as follows for a single bottle
{
"data":{
"id":"cc134653-c463-4e79-8b9e-f52dfe02498e",
"type":"bottle",
"attributes":{
"name":"Luc Belaire Rare Luxe",
"price":"$29.99",
"image":"https://cdn11.bigcommerce.com/s-7a906/images/stencil/1000x1000/products/10929/10518/Luc-Belaire-Rare-Luxe__73902.1555086630.jpg?c=2",
"sku":"813497005010",
"size":"750ML",
"origination":"France",
"varietal":"Sparkling Wine"
}
}
}
I am new to React so I could be mistaken here, but this function is intended to display a loader, just a simple fontawesome spinner, until the data is available.
Here is the function
import React, { useState, useEffect } from 'react';
import { Loader } from '../../components/Loader'
import { endpoints } from "../../utils/fetch";
export default function Bottle({ match }) {
let [bottle, setBottle] = useState([])
useEffect(() => {
fetch(`${endpoints().bottle}/${match.params.sku}`, { method: "GET" })
.then(response => response.json())
.then(data => setBottle(data.data))
}, [])
return (
!bottle ? <Loader /> :
<div className="card">
<div className="card-body">
<div className="row">
<div className="mb-4 mb-lg-0 col-lg-6">
<div>
<div className="position-relative h-sm-100 overflow-hidden">
<img className="img-fluid fit-cover w-sm-100 h-sm-100 rounded cursor-pointer"
src={bottle.attributes.image}
alt={bottle.attributes.name}
height={200}
width={125} />
</div>
</div>
</div>
<div className="d-flex justify-content-between flex-column col-lg-6">
<div>
<h5>Apple iMac Pro (27-inch with Retina 5K Display, 3.0GHz 10-core Intel Xeon W, 1TB SSD)</h5>
<a className="fs--1 mb-2 d-block" href="#!">Computer & Accessories</a>
<h4 className="d-flex align-items-center"><span className="text-warning mr-2">$1199.50</span></h4>
<p className="fs--1 mb-1"><span>Shipping Cost: </span><strong>$50</strong></p>
<p className="fs--1">Stock: <strong className="text-success">Available</strong></p>
</div>
<div className="row">
<div className="col-auto">
<button type="button" className="border-300 mr-2 btn btn-outline-danger btn-sm">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="heart" className="svg-inline--fa fa-heart fa-w-16 mr-1" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path fill="currentColor" d="M462.3 62.6C407.5 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z" />
</svg>
282
</button>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
I would expect, based on what I've written, that the loader would display until the bottle
has is not null. Instead, I get the following error.
Am I misusing state here? I've tried to use async
and await
here but was not successful in getting the data to display. Just the same error.
Upvotes: 0
Views: 260
Reputation: 4651
Your default value for bottle
is []
, in JavaScript, an empty array is still considered truthy, so this will result in your component following the else path before your data has finished loading.
Also, when you are rendering the component, you are not using the data as an array anyway.
Change your useState to this:
let [bottle, setBottle] = useState();
This will provide a default value of undefined
to bottle
, which should mean your ternary will behave correctly.
Upvotes: 1