在我的应用程序中,我正在实现产品列表页面,该页面列出了列表页面上的产品。我希望基于这篇文章整合一些好的实践 - https://dev.to/vyan/using-async-functions-in-useeffect-best-practices-and-pitfalls-o75 但不是
let
我正在使用 ref
进行跟踪。
我在控制台消息中获取产品列表,但它在 UI 中不显示任何列表。当我在清理函数中注释 -
isMounted.current = false;
行时,只有它显示列表。让我知道我在清理过程中做错了什么?
App.jsx -
import { useEffect, useRef, useState } from "react";
import ProductsList from "./components/ProductsList";
import "./styles.css";
export default function App() {
const isMounted = useRef(true);
const [products, setProducts] = useState([]);
const fetchData = async () => {
try {
const data = await fetch("https://dummyjson.com/products");
const { products = [] } = await data.json();
console.log(products); // It shown as Array of object in the console
if (isMounted.current) {
setProducts(products);
}
} catch (error) {
if (isMounted.current) {
console.error("Error fetching data: ", error);
}
}
};
useEffect(() => {
fetchData();
return () => {
isMounted.current = false; // Cleanup on unmount
};
}, []);
return (
<div className="App">
<h1>Product Listing Page</h1>
{products.length ? <ProductsList products={products} /> : null}
</div>
);
}
ProductsList.jsx -
const ProductsList = ({ products }) => {
return (
<div className="products-list">
{products.map((product) => {
return (
<div className="product" key={product.id}>
<div className="max-w-sm rounded overflow-hidden shadow-lg">
<img
className="w-full"
src={product.thumbnail}
alt={product.thumbnail}
/>
<div className="px-6 py-4">
<div className="font-bold text-xl mb-2">{product.title}</div>
<p className="text-gray-700 text-base">{product.description}</p>
</div>
<div className="px-6 pt-4 pb-2">
{product.tags.map((tag, index) => (
<span
key={index}
className="inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold text-gray-700 mr-2 mb-2"
>
#{tag}
</span>
))}
</div>
</div>
</div>
);
})}
</div>
);
};
export default ProductsList;
在 React Strict 模式下,React 调用效果设置和清理函数(模拟挂载/卸载)。因此,当第二次重新调用 setup 函数时,在 cleanup 函数中更新的 ref 值仍将被设置为
false
(请参阅 此讨论,了解这是否是预期行为)。
React 团队不鼓励使用引用来检测安装,并且建议也使用变量(如您的文章中提到的那样)来确定组件是否已卸载。
如果必须使用引用,则可以在初始安装时将引用重置为
true
(本质上“撤消”严格模式清理调用的影响):
useEffect(() => {
isMounted.current = true;
fetchData();
return () => {
isMounted.current = false; // Cleanup on unmount
};
}, []);
但是,我建议您尝试使用文档中建议的变量方法来避免这种模式。