这是我在 React.js 中的第一个电子商务项目。
我正在显示产品列表,其中我也在左侧显示类别,如下面的屏幕截图所示。
我正在尝试根据类别过滤产品列表。因此,我非常接近实现它,但我面临一个错误(内存泄漏问题)。
错误: 警告:超出最大更新深度。当组件在 useEffect 中调用 setState,但 useEffect 没有依赖项数组,或者依赖项之一在每次渲染时发生更改时,就会发生这种情况。
我哪里出错了? 这是截图:
这是代码:
const [products, setProducts] = useState([]);
const [page, setPage] = useState(1);
const [categories, setCategories] = useState([]);
const [selectedCategories, setSelectedCategories] = useState([]);
//handling paging
const handlePageChange = (pageNumber) => {
if (
pageNumber > 0 &&
pageNumber <= products.length / 15 &&
pageNumber !== page
)
setPage(pageNumber);
}
const addCategory = (category) => {
if(!selectedCategories.includes(category)){
setSelectedCategories(prev => ([...prev, category]))
}
}
const removeCategory = (category) => {
if(selectedCategories.includes(category)){
const removedList = selectedCategories.filter((item) => (item !== category));
setSelectedCategories(removedList);
}
}
const getCategories = () => {
fetch('https://dummyjson.com/products/categories')
.then(res => res.json())
.then((data) => {
setCategories(data);
})
.catch((err) => console.log(err));
}
useEffect(() => {
getCategories()
}, [])
const getProducts = () => {
fetch('https://dummyjson.com/products?limit=90')
.then(res => res.json())
.then((data) => {
if (data.products && data.products.length) setProducts(data.products);
})
.catch((err) => console.log(err));
}
useEffect(() => {
getProducts()
}, [])
useEffect(() => {
if(selectedCategories.length === 0){
setProducts(products);
} else{
setProducts(products.filter((item)=>(selectedCategories.includes(item.category))));
}
}, [selectedCategories, products])
这是 JSX 代码: 显示类别。
{categories.map((category) => (
<div onClick={() => {
if(selectedCategories.includes(category)){
removeCategory(category);
} else{
addCategory(category);
}
}} key={category}>
<div className="form-check">
<input className="form-check-input" type="checkbox" value={category} id={category} />
<label className="form-check-label" htmlFor={category}>
{category}
</label>
</div>
</div>
))}
显示产品列表。
{products.length && (
<div className='row'>
{products.slice(page * 15- 15, page * 15).map((item) => (
<div className='col-lg-4 mb-4 text-center' key={item.id}>
<div className='product' key={item.id}>
<Link to={`/shop/${item.id}/${item.title.replace(/\s+/g, '-').toLowerCase()}`}>
<div className='list'>
<div className='p_photo'>
<img className='img-fluid' src={item.thumbnail} alt={item.title} />
</div>
</div>
</Link>
<div className="Stars" style={{"--rating": [item.rating]}} />
<div className='title mt-2'> <Link to={`/shop/${item.id}/${item.title.replace(/\s+/g, '-').toLowerCase()}`}>{item.title}</Link> </div>
<div className='price mt-2'>
<span className='sale'>${item.price}</span>
<span className='discount'>({item.discountPercentage}% OFF)</span>
</div>
</div>
</div>
))}
</div>
)}
问题出现在这里:组件挂载后,它在第一个 useEffect 中调用
getProducts()
。随后,在获取数据后,它会更新 products
状态,触发第二个 useEffect。在第二个 useEffect 中,您已将 [selectedCategories, products]
设置为依赖项数组。
如果
selectedCategories
为空数组,则会进入if语句,调用setProducts(products)
,再次触发useEffect,产生递归。
const getProducts = () => {
fetch('https://dummyjson.com/products?limit=90')
.then(res => res.json())
.then((data) => {
if (data.products && data.products.length) setProducts(data.products);
})
.catch((err) => console.log(err));
}
useEffect(() => {
getProducts()
}, [])
useEffect(() => {
if(selectedCategories.length === 0){
setProducts(products);
} else{
setProducts(products.filter((item)=>(selectedCategories.includes(item.category))));
}
}, [selectedCategories, products])