我正在从useEffect对firebase进行API调用,当页面第一次加载时,返回的数据是空的,但如果我对代码进行任何更改并保存它,则会填充数据。我希望数据在页面第一次加载时出现。
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { motion } from "framer-motion";
import { getDatabase, ref, onValue } from "firebase/database";
import Helmet from "../components/Helmet/Helmet";
import "../styles/home.css";
import { Container, Row, Col } from "reactstrap";
import heroImg from "../assets/images/hero-img.png";
import Services from "../services/Services";
import ProductsList from "../components/UI/ProductsList";
import Clock from "../components/UI/Clock";
import counterImg from "../assets/images/counter-timer-img.png";
const Home = () => {
const [isLoading, setIsLoading] = useState(true);
const [products, setProducts] = useState([]);
const [trendingProducts, setTrendingProducts] = useState([]);
const [bestSalesProducts, setBestSalesProducts] = useState([]);
const [mobileProducts, setMobileProducts] = useState([]);
const [wirelessProducts, setWirelessProducts] = useState([]);
const [popularProducts, setPopularProducts] = useState([]);
const year = new Date().getFullYear();
useEffect(() => {
const fetchProducts = () => {
const db = getDatabase();
const thumbnailRef = ref(db, "Contents/");
onValue(thumbnailRef, (snapshot) => {
const data = snapshot.val();
if (data !== null) {
Object.values(data).map((product) => {
return setProducts((oldArray) => [...oldArray, product]);
});
console.log(products);
}
});
};
const filteredTrendingProducts = products.filter(
(item) => item.category === "Kids"
);
const filteredBestSalesProducts = products.filter(
(item) => item.category === "Entertainment"
);
const filteredMobileProducts = products.filter(
(item) => item.category === "LifeStyle"
);
const filteredWirelessProducts = products.filter(
(item) => item.category === "wireless"
);
const filteredPopularProducts = products.filter(
(item) => item.category === "watch"
);
setTrendingProducts(filteredTrendingProducts);
setBestSalesProducts(filteredBestSalesProducts);
setMobileProducts(filteredMobileProducts);
setWirelessProducts(filteredWirelessProducts);
setPopularProducts(filteredPopularProducts);
setIsLoading(false);
fetchProducts();
}, []);
if (isLoading) {
return <div> Loading ... </div>;
}
return (
whileTap={{ scale: 1.2 }}
className="buy__btn store__btn"
>
<Link to="/shop">Visit Store</Link>
</motion.button>
</Col>
<Col lg="6" md="12" className="text-end counter__img">
<img src={counterImg} alt="" />
</Col>
</Row>
</Container>
</section>
<section className="new__arrivals">
<Container>
<Row>
<Col lg="12" className="text-center mb-5">
<h2 className="section__title">New Arrivals</h2>
</Col>
<ProductsList data={mobileProducts} />
<ProductsList data={wirelessProducts} />
</Row>
</Container>
</section>
<section className="popular_category">
<Container>
<Row>
<Col lg="12" className="text-center mb-5">
<h2 className="section__title">Popular in Category</h2>
</Col>
<ProductsList data={popularProducts} />
</Row>
</Container>
</section>
</Helmet>
);
};
export default Home;
我尝试过将产品添加为useEffect依赖项,但它会创建一个无限循环获取。
在第一次页面加载时,我需要做什么来获取数据?
2条答案
按热度按时间ddrv8njm1#
如果
setProducts()
之后的console.log(products)
返回undefined
,这是正常的,因为setProducts()
是异步的,并且在记录日志时products
尚未更新。添加
products
作为依赖项将创建无限循环,因为同一个useEffect
同时设置和侦听products
。但是,如果您愿意,可以将筛选器的逻辑分离到第二个
useEffect
,并添加products
作为其依赖项,因为筛选器实际上依赖于products
。示例:
第一个
to94eoyn2#
setState in react是异步的。在这里阅读更多。所以当你设置你的状态(产品)时,它需要一些时间来实际更新你的状态。
为了解决您的问题,您有两个选择。
首先是在products状态上编写另一个useEffect,并将逻辑移到那里,如下所示:
另一种方法是使用async/await,将产品存储在一个temp变量中,并使用该变量而不是state:
如果函数不是异步的,也可以删除async/await。