【发布时间】:2021-05-19 12:34:03
【问题描述】:
我正在使用带有 typescript 和自制 RESTapi 的 React。我在一个页面上发出 GET 请求,由于某种原因,我的网站非常慢,有时甚至完全阻塞了 UI - 这在 getData() 和 renderMultipleCards() 函数中实现 GET RESTapi 调用后开始发生。
有谁知道为什么会这样,以及如何解决?
import "../css/stylesheet.css";
import Image from 'react-bootstrap/Image'
import Omnivores from "../images/ProductBanners/omnivoresCrop.png";
import Carnivores from "../images/ProductBanners/CarnivoreCrop.png";
import Herbivores from "../images/ProductBanners/herbivoreCrop.png";
import Small from "../images/ProductBanners/smallDinosaursCrop.png";
import Medium from "../images/ProductBanners/mediumDinosaursCrop.jpg";
import Large from "../images/ProductBanners/largeDinosCrop.png";
import React, { useEffect, useState } from "react";
import { Button, Card, CardDeck } from "react-bootstrap";
const ALL_DINOS = "http://localhost:3000/velocishop/products";
const SMALL_DINOS = "http://localhost:3000/velocishop/size/Small/products";
const MEDIUM_DINOS = "http://localhost:3000/velocishop/size/Medium/products";
const LARGE_DINOS = "http://localhost:3000/velocishop/size/Large/products";
const CARNIVORE_DINOS = "http://localhost:3000/velocishop/diet/Carnivore/products";
const HERBIVORE_DINOS = "http://localhost:3000/velocishop/diet/Herbivore/products";
const OMNIVORE_DINOS = "http://localhost:3000/velocishop/diet/Omnivore/products";
const ALL_DINOS_API_CALL = "http://localhost:3005/velocishop/products";
const SMALL_DINOS_API_CALL = "http://localhost:3005/velocishop/size/Small/products";
const MEDIUM_DINOS_API_CALL = "http://localhost:3005/velocishop/size/Medium/products";
const LARGE_DINOS_API_CALL = "http://localhost:3005/velocishop/size/Large/products";
const CARNIVORE_DINOS_API_CALL = "http://localhost:3005/velocishop/diet/Carnivore/products";
const HERBIVORE_DINOS_API_CALL = "http://localhost:3005/velocishop/diet/Herbivore/products";
const OMNIVORE_DINOS_API_CALL = "http://localhost:3005/velocishop/diet/Omnivore/products";
export default function AllProducts() {
var header: string = "";
var url: string = "";
var apiUrl: string = "";
const [dinos, setDinos] = useState<Array<any>>([]);
const handleSetDinos = (e: any) => {
setDinos(e);
console.log(dinos)
};
const renderImageAndHeader = () => {
url = window.location.href
switch (url) {
case ALL_DINOS: {
header = "All Dinosaurs"
apiUrl = ALL_DINOS_API_CALL
console.log(apiUrl)
return Omnivores
}
case SMALL_DINOS: {
header = "Small Dinosaurs"
apiUrl = SMALL_DINOS_API_CALL
console.log(url)
return Small
}
case MEDIUM_DINOS: {
header = "Medium Dinosaurs"
apiUrl = MEDIUM_DINOS_API_CALL
console.log(url)
return Medium
}
case LARGE_DINOS: {
header = "Large Dinosaurs"
apiUrl = LARGE_DINOS_API_CALL
console.log(url)
return Large
}
case CARNIVORE_DINOS: {
header = "Carnivore Dinosaurs"
apiUrl = CARNIVORE_DINOS_API_CALL
console.log(url)
return Carnivores
}
case HERBIVORE_DINOS: {
header = "Herbivore Dinosaurs"
apiUrl = HERBIVORE_DINOS_API_CALL
console.log(url)
return Herbivores
}
case OMNIVORE_DINOS: {
header = "Omnivore Dinosaurs"
apiUrl = OMNIVORE_DINOS_API_CALL
console.log(url)
return Omnivores
}
}
}
function getData(url: string) {
fetch(url, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
})
.then(response => response.json())
.then((data) => {
handleSetDinos(data)
})
.catch(err => console.log(err))
}
function renderMultipleCards() {
getData(apiUrl)
return (
<CardDeck>
{dinos.map((dino) => (
<div key={dino}>
<Card>
<Card.Body>
<Card.Title>{dino.productName}</Card.Title>
<Card.Text>
{dino.size},
{dino.diet},
{dino.price}
</Card.Text>
</Card.Body>
<Button variant="primary">Add to cart</Button>
</Card>
</div>
))}
</CardDeck>
)
}
return (
<div>
<div className="banner-wrapper">
<Image src={renderImageAndHeader()} fluid />
</div>
<div className="for-small-screen-display"><h1>{header}</h1></div>
<div className="card-wrapper">
{renderMultipleCards()}
</div>
</div>
);
}
【问题讨论】:
-
getData是异步操作(从 API 获取数据)。您不能调用它,然后只需映射下一行的数据。花一点时间研究 Javascript 中的同步与异步代码以及它们各自的含义。最重要的是,您在函数中调用renderMultipleCards(),调用getData(apiUrl)的主体,执行API 请求然后设置状态。该状态更改将触发重新渲染,导致再次调用renderMultipleCards()并且循环将重新开始,无限循环。需要在组件挂载时调用一次,设置好数据后渲染
标签: node.js reactjs typescript express rest