React中map内更新状态触发Too many re-renders错误的解决方法
修复React购物车组件的Too many re-renders错误
错误原因
你在组件渲染阶段(map循环内部)直接调用setPrice更新状态,每次状态更新都会触发组件重新渲染,而重新渲染又会再次调用setPrice,形成无限循环,最终触发Too many re-renders错误。
修复方案
方案1:使用useEffect监听商品变化计算总价
如果需要把总价存在状态中,可通过useEffect监听购物车商品列表的变化,仅在商品数据更新时重新计算总价:
const Cart = () => { const { value, setValue } = useContext(UserContext) const [totalPrice, setTotalPrice] = useState(0) // 监听购物车商品变化,计算总价 useEffect(() => { if (value) { const calculatedTotal = value.reduce((sum, product) => { return sum + Number(product[3]) }, 0) setTotalPrice(calculatedTotal) } else { setTotalPrice(0) } }, [value]) // 仅当value变化时执行计算 if (!value) { return <h1>Cart is empty</h1> } return ( <div> {value.map((product, index) => ( <ProductToCart key={index} // 必须添加key,避免React渲染警告 name={product[0]} img={product[1]} discription={product[2]} price={product[3]} /> ))} {/* 展示计算后的总价 */} <div>总价:{totalPrice}元</div> </div> ) }
方案2:直接计算派生值(无需状态存储)
总价属于派生状态(完全由购物车商品数据决定),可以直接在渲染时计算,无需单独用useState存储,更简洁高效:
const Cart = () => { const { value, setValue } = useContext(UserContext) // 直接计算总价,无需状态维护 const totalPrice = value ? value.reduce((sum, product) => sum + Number(product[3]), 0) : 0 if (!value) { return <h1>Cart is empty</h1> } return ( <div> {value.map((product, index) => ( <ProductToCart key={index} name={product[0]} img={product[1]} discription={product[2]} price={product[3]} /> ))} <div>总价:{totalPrice}元</div> </div> ) }
核心原则
永远不要在组件渲染阶段直接调用状态更新函数,状态更新应该放在事件处理函数、副作用钩子(如useEffect)或其他非渲染触发的逻辑中。
内容的提问来源于stack exchange,提问作者M. Khromov
相关产品推荐
相关产品推荐

