如何解决UseEffect在React中运行无限渲染超过最大更新深度
我有一个Cart组件,里面有一系列Cards。
每次用户从购物车中删除产品时,我都会从本地存储中删除产品, 并将其从用户界面中删除。
import React,{ useState,useEffect } from 'react';
import { Link } from 'react-router-dom';
import Layout from '../Layout';
import Card from '../Home/Card';
import { getCart } from './cartHelpers';
const Cart = () => {
const [items,setItems] = useState([]);
useEffect(() => {
setItems(getCart());
},[items]);
const showItems = () => {
return (
<div>
<h2>You have {`${items.length}`} items in your cart</h2>
<hr />
{items.map((prod,index) => (
<Card key={prod._id}
....... />
))}
</div>
);
};
const noItemsMsg = () => (
<h2>
Your cart is empty! <br /> <Link to='/shop'>Continue Shopping</Link>
</h2>
);
return (
<Layout
title='Shopping Cart'
desc='Manage your cart items'
className='container-fluid'
>
<div className='row'>
<div className='col-6'>
{items && items.length > 0 ? showItems(items) : noItemsMsg()}
</div>
<div className='col-6'>
<p>
Show Checkout Options / Shipping Address / Total / Update Quantity
</p>
</div>
</div>
</Layout>
);
};
export default Cart;
和 Card.js :
import React,{ useState } from 'react';
import moment from 'moment';
import { Link,Redirect } from 'react-router-dom';
import ShowImage from '../ShowImage';
import { addItemToCart,updateItem,removeItem } from '../Cart/cartHelpers';
const Card = ({product,.............
}) => {
const [redirect,setRedirect] = useState(false);
const [countHowManyCopies,setCountHowManyCopies] = useState(product.count);
const showRemoveButton = () => {
return (
showRemoveProductBtn && (
<button
onClick={() => removeItem(product._id)}
className='btn btn-outline-danger mt-2 mb-2'
>
Remove Product
</button>
)
)
};
return (
<div className={!showProductFullSize ? 'col-4 mb-3' : ''}>
<div className='card'>
<div className='card-header name'>{product.name}</div>
<div className='card-body'>
.............. // more code
{showRemoveButton()}
.............. // more code
</div>
</div>
</div>
);
};
export default Card;
只要用户点击“删除项目”按钮,我都会得到:
Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect,but useEffect either doesn't have a dependency array,or one of the dependencies changes on every render.
解决此问题的最佳方法是什么?
发生这种情况是由于这段代码(数组中的items
):
useEffect(() => {
setItems(getCart());
},[items]);
解决方法
我想您在渲染组件时会收到“超出最大更新深度”警告,无需等待单击“删除”按钮。 原因是:项目更改时将调用setItems,然后setItems将更改项目,因此将导致无限递归。
useEffect(() => {
setItems(getCart());// setItems will change the items
},[items]);
噢,我认为当前的方法不是干净的方法,因为通过这种方法很难控制组件的重新渲染。 我的建议是删除useEffect的使用,然后添加onRemoveItems作为CardComponent的道具
import { addItemToCart,updateItem,removeItem } from '../Cart/cartHelpers';
const Cart = () => {
const [items,setItems] = useState([]);
//remove this
//useEffect(() => {
// setItems(getCart());
//},[items]);
const removeItem = (id) => {
removeItem(id);
setItems(getCart());
}
const showItems = () => {
return (
<div>
<h2>You have {`${items.length}`} items in your cart</h2>
<hr />
{items.map((prod,index) => (
<Card key={prod._id} onRemoveItem={removeItem}
....... />
))}
</div>
);
};
const Card = ({product,.............
}) => {
const [redirect,setRedirect] = useState(false);
const [countHowManyCopies,setCountHowManyCopies] = useState(product.count);
const showRemoveButton = () => {
return (
showRemoveProductBtn && (
<button
onClick={() => props.onRemoveItem(product._id)}
className='btn btn-outline-danger mt-2 mb-2'
>
Remove Product
</button>
)
)
};
return (
<div className={!showProductFullSize ? 'col-4 mb-3' : ''}>
<div className='card'>
<div className='card-header name'>{product.name}</div>
<div className='card-body'>
.............. // more code
{showRemoveButton()}
.............. // more code
</div>
</div>
</div>
);
};
export default Card;
,
问题的根本原因在于使用' useEffect '更新状态。
useEffect 仅可用于执行副作用。
副作用是由于状态变化而触发的活动。
一些副作用的例子是:
- 用户提供输入数据后提交表单。
- 页面加载时从API提取JSON数据。
更新 useEffect 内部的状态可能会导致无限循环。
注意到的问题是在useEffect中更新状态的示例。
-
每当调用 setItems 时,“ 项目”的状态就会得到 改变了。
-
状态更改将出于运行的目的触发 useEffect 副作用。
-
useEffect 再次调用 setItems ,这将导致无限循环。
如何解决问题?
可以通过除去 useEffect 钩子来解决该问题,因为在给定情况下这不是必需的。
,在Cart.js文件中:从useEffect中删除项目依赖项。在此处导入removeItem
import { removeItem } from '../Cart/cartHelpers';
const Cart = () => {
const [items,setItems] = useState([]);
useEffect(() => {
setItems(getCart());
},[]);
// Add this function and pass it to Card component
const handleRemove = (id) => {
removeItem(id)
setItems(getCart())
}
const showItems = () => {
return (
<div>
<h2>You have {`${items.length}`} items in your cart</h2>
<hr />
{items.map((prod,index) => (
<Card key={prod._id} handleRemove={handleRemove}
....... />
))}
</div>
);
};
Card.js-接收handleRemove作为道具
const Card = ({product,handleRemove
.............
}) => {
const [redirect,setCountHowManyCopies] = useState(product.count);
const showRemoveButton = () => {
return (
showRemoveProductBtn && (
<button
onClick={() => handleRemove(product._id)}
className='btn btn-outline-danger mt-2 mb-2'
>
Remove Product
</button>
)
)
};...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。