![](/img/trans.png)
[英]How can I render Component with updated data after useEffect, the useEffect fetches data from an API
[英]how can I transfer the data to another component (useEffect problem)
在 useEffect 中,我從服務器檢索數據並將其存儲在“products”數組中:
const { url } = props;
const [products, setProducts] = useState([]);
useEffect(() => {
const fetchProducts = async () => {
setLoadingSpinner(true);
const response = await fetch(url);
const responseData = await response.json();
setLoadingSpinner(false);
const loadedProducts = [];
for (const key in responseData) {
loadedProducts.push({
id: key,
name: responseData[key].name,
description: responseData[key].description,
price: responseData[key].price,
image: responseData[key].image,
processor: responseData[key].processor,
});
}
setProducts(loadedProducts);
setIsDataLoaded(true);
};
fetchProducts();
}, [url, isDataLoaded]);
我將它傳遞給 ProductDetail 組件:
<ProductDetail products={products}></ProductDetail>
我總是在 ProductDetail 組件中得到一個 null 值:
function ProductDetail(props) {
const params = useParams();
const [product, setProduct] = useState(null);
useEffect(() => {
if (props.products && params.productId) {
const product = props.products.find(product => product.id === params.productId);
setProduct(product);
}
}, [props.products, params.productId]);
console.log(product)
我意識到當 useEffect 第一次運行時,我的“products”數組仍然是空的,它會將它發送到組件,所以這並不好。 但我不知道如何解決這個問題。
這里有一些錯誤。 我將從一開始看起來切線的東西開始,但它會導致更好的答案。
在ProductDetail
中,您引入了一個名為product
的新 state。 然后,在useEffect
中,從 props 中的列表和產品 ID 中找到產品,並將其設置回 state 項目。 這將是不必要的 state 重復(即使沒有將 prop 逐字復制到 state,直接從 props 派生的值仍然很重要)並且會增加應用程序中錯誤的表面積(這可能是最常見的初學者錯誤)。
你實際上不需要那個 state 項目,你只需要useMemo
:
function ProductDetail(props) {
const params = useParams();
const product = useMemo(() => {
if (props.products && params.productId) {
return props.products.find(product => product.id === params.productId);
}
}, [props.products, params.productId]);
console.log(product)
要解決在加載產品時暫時找不到產品的問題,您可以 (a) 有條件地呈現組件,這樣當尚未獲取products
時,此代碼甚至不會首先運行。 或者 (b) 更改ProductDetail
,使其在找到產品之前什么都不做。
溶液A
const [products, setProducts] = useState(null); // We change the default to null to be able to distinguish empty list case from loading case.
// ...
{products !== null && <ProductDetail products={products}></ProductDetail>}
溶液B
function ProductDetail(props) {
const params = useParams();
const product = useMemo(() => {
if (props.products && params.productId) {
return props.products.find(product => product.id === params.productId);
}
}, [props.products, params.productId]);
if (!product) return null // Return early (do nothing) whilst product is not found
// ... your original render contents
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.