[英]React useEffect is returning empty data when page loads for the first time
[英]React useEffect is returning empty data array when page loads for the first time
我正在从 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 依赖项,但它会创建无限循环获取。
我需要做什么才能在第一页加载时获取数据?
如果console.log(products)
在setProducts()
之后立即返回undefined
是正常的,因为setProducts()
是异步的并且记录时products
尚未更新。
将products
添加为依赖项将创建一个无限循环,因为同一个useEffect
既设置又监听products
。
但是,如果您愿意,您可以将过滤器的逻辑分离到第二个useEffect
并将products
添加为其依赖项,因为过滤实际上依赖于products
。
例子:
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);
}
});
};
setIsLoading(false);
fetchProducts();
}, []);
useEffect(() => {
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);
}, [products]);
react 中的 setState 是异步的。 在这里阅读更多。 因此,当您设置 state(产品)时,实际更新您的 state 需要一些时间。
为了解决您的问题,您有两种选择。
首先是在您的产品 state 上编写另一个 useEffect 并将您的逻辑移动到那里,如下所示:
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);
}
});
};
fetchProducts();
}, []);
useEffect(() => {
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);
}, [procuts]);
另一种方法是使用异步/等待并将您的产品存储在临时变量中并使用该变量而不是 state:
useEffect(async () => {
let tempProducts = [];
const fetchProducts = async () => {
const db = await getDatabase();
const thumbnailRef = await ref(db, "Contents/");
await onValue(thumbnailRef, (snapshot) => {
const data = snapshot.val();
if (data !== null) {
Object.values(data).map((product) => {
tempProducts = [...products, product]
return setProducts(tempProducts);
});
console.log(tempProducts);
}
});
};
const filteredTrendingProducts = tempProducts.filter(
(item) => item.category === "Kids"
);
const filteredBestSalesProducts = tempProducts.filter(
(item) => item.category === "Entertainment"
);
const filteredMobileProducts = tempProducts.filter(
(item) => item.category === "LifeStyle"
);
const filteredWirelessProducts = tempProducts.filter(
(item) => item.category === "wireless"
);
const filteredPopularProducts = tempProducts.filter(
(item) => item.category === "watch"
);
setTrendingProducts(filteredTrendingProducts);
setBestSalesProducts(filteredBestSalesProducts);
setMobileProducts(filteredMobileProducts);
setWirelessProducts(filteredWirelessProducts);
setPopularProducts(filteredPopularProducts);
setIsLoading(false);
await fetchProducts();
}, []);
如果函数不是异步的,您也可以删除 async/await。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.