I'm new to react.js Please help me to find what I'm doing wrong I'm getting the list of items from API and I want to implement a Loader while loading the data. I'm using if statement if as you can see in the code. Is there another way to achieve the similar thing. This is how I'm doing...
import React, { useState, useEffect } from "react";
import { ListGroup, Row, Card, Container, Col } from "react-bootstrap";
import Loader from "../components/Loader";
const fetchURL = "api/guide/";
const getItems = () => fetch(fetchURL).then((res) => res.json());
function Guide() {
const [items, setItems] = useState([]);
useEffect(() => {
getItems().then((data) => setItems(data));
}, []);
return (
<Row>
<Container fluid>
{items ? (
items.map((item) => (
<ListGroup
className="mb-3 my-3 p-1 rounded"
variant="success"
>
<ListGroup.Item
style={{
width: "auto",
height: "auto",
}}
className="mb-2 my-2 p-2 rounded"
variant="flush"
>
<Row>
<Col md="7">
<h3 className="mx-3">
<strong>{item.title}</strong>
</h3>
<Card.Body>
<p>{item.description}</p>
</Card.Body>
</Col>
<Col md="5">
{item.ytVidLink ? (
<Card className="my-2 p-2 rounded card border-light">
{" "}
<div className="video-responsive">
<iframe
width="1200"
height="720"
src={`https://www.youtube.com/embed/${item.ytVidLink}`}
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
title="Embedded youtube"
/>
</div>
</Card>
) : (
<div variant="light"> </div>
)}
</Col>
</Row>
</ListGroup.Item>
</ListGroup>
))
) : (
<Loader />
)}
</Container>
</Row>
);
}
export default Guide;
Data coming as expected but Loader is loading as I want.
CodePudding user response:
import React, { useState, useEffect } from "react";
import { ListGroup, Row, Card, Container, Col } from "react-bootstrap";
import Loader from "../components/Loader";
const fetchURL = "api/guide/";
const getItems = () => fetch(fetchURL).then((res) => res.json());
function Guide() {
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true)
useEffect(() => {
getItems().then((data) => {
setItems(data);
setLoading(false);
});
}, []);
return (
<Row>
<Container fluid>
{items ? (
items.map((item) => (
<ListGroup
className="mb-3 my-3 p-1 rounded"
variant="success"
>
<ListGroup.Item
style={{
width: "auto",
height: "auto",
}}
className="mb-2 my-2 p-2 rounded"
variant="flush"
>
<Row>
<Col md="7">
<h3 className="mx-3">
<strong>{item.title}</strong>
</h3>
<Card.Body>
<p>{item.description}</p>
</Card.Body>
</Col>
<Col md="5">
{item.ytVidLink ? (
<Card className="my-2 p-2 rounded card border-light">
{" "}
<div className="video-responsive">
<iframe
width="1200"
height="720"
src={`https://www.youtube.com/embed/${item.ytVidLink}`}
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
title="Embedded youtube"
/>
</div>
</Card>
) : (
<div variant="light"> </div>
)}
</Col>
</Row>
</ListGroup.Item>
</ListGroup>
))
) : ''}
{loading ? <Loader /> : ''}
</Container>
</Row>
);
}
export default Guide;
Added a loading state and initially, its value is true. so it will show loading and after getting the data from API we will change loading state to false
by using this method even if your API returns empty results it will work very fine. but in your method, if you get an empty result from API it will not stop loading!
CodePudding user response:
You're initializing items
to an empty array which will evaluate to true in a boolean context. So your condition (items ?
) is always true. You could test items.length
instead.