用功能组件中的另一个状态更新状态
update state with another state in functional component
我有一个状态,每次当另一个状态时都需要更新 changes.So 我使用了另一个状态的依赖数组项的效果,但它导致了无限渲染。
我想将这些变量用作状态。
我希望 totalAmount 成为一个状态变量,其他变量需要成为状态(折扣小计等)。
有什么解决办法。
App.js
import { useState, useEffect } from 'react';
import './styles.css';
function App() {
let order = [
{
qty: 2,
name: 'Margarita A',
variant: 'crab & cucumber',
price: '412.00',
}
];
let [discount, setDiscount] = useState(759.5),
[deliveryFee, setDeliveryFee] = useState(12.0),
[taxes, setTaxes] = useState(46.15),
[subtotal, setSubtotal] = useState(0),
[totalAmount, setTotalAmount] = useState(0);
useEffect(() => {
setTotalAmount(subtotal - discount + deliveryFee + taxes);
}, [subtotal, discount, deliveryFee, taxes]);
return (
<div className="app">
<div className="container">
<div className="orderItems">
{order.map((item, i) => {
// subtotal += +item.price;
setSubtotal((prev) => prev + +item.price);
return (
<div className="orderItem" key={i}>
<span className="orderItemPrice">₹{item.price}</span>
</div>
);
})}
</div>
</div>
<div className="summary">
<span className="summaryTitle">Summary</span>
<div className="total amountBox">
<span>Total</span>
<span>₹ {totalAmount}</span>
</div>
</div>
</div>
<div className="placeOrder">
<button onClick={(e, totalAmount) => {}}>PLACE ORDER</button>
</div>
</div>
);
}
export default App;
问题
问题不在于您的 useEffect
挂钩,它工作正常并在组件挂载时调用一次。问题出在 return
方法中的 setSubtotal((prev) => prev + +item.price);
。
状态变量的每次更改都会导致重新渲染,每次重新渲染都会重新创建您的 order.map
。因此在 order.map
期间更改状态将导致重新渲染,而重新渲染会导致 order.map
再次绘制。这是无限重新渲染的原因。
注意: 您可以简单地在 map
函数中注释 setState
来阻止这种行为。
解决方案
有一些选项可以控制这种情况,例如对 subtotal
使用 useRef
来防止重新渲染的原因。
此外,您可以在计算 totalAmount
和设置它之前在 useEffect
钩子中计算 subtotal
。
function App() {
let order = [
{
qty: 2,
name: "Margarita A",
variant: "crab & cucumber",
price: "412.00"
}
];
const [discount, setDiscount] = useState(59.5);
const [deliveryFee, setDeliveryFee] = useState(12.0);
const [taxes, setTaxes] = useState(46.15);
const [subtotal, setSubtotal] = useState(0);
const [totalAmount, setTotalAmount] = useState(0);
useEffect(() => {
const localSubtotal = order.reduce(
(acc, curr) => (acc += Number(curr.price)),
0
);
setSubtotal(localSubtotal);
setTotalAmount(localSubtotal - discount + deliveryFee + taxes);
}, [discount, deliveryFee, taxes, order]);
return (
<div className="app">
<div className="container">
<div className="orderItems">
{order.map((item, i) => {
return (
<div className="orderItem" key={i}>
<span className="orderItemPrice">₹{item.price}</span>
</div>
);
})}
</div>
</div>
<div>
<div className="summary">
<div>
<span>Sub Total: {subtotal}</span>
</div>
<span className="summaryTitle">Summary</span>
<div className="total amountBox">
<span>Total</span>
<span>₹ {totalAmount}</span>
</div>
</div>
</div>
<div className="placeOrder">
<button onClick={(e, totalAmount) => {}}>PLACE ORDER</button>
</div>
</div>
);
}
export default App;
注意:不要忘记在useEffect
hook的依赖数组中传递order
数组。
我有一个状态,每次当另一个状态时都需要更新 changes.So 我使用了另一个状态的依赖数组项的效果,但它导致了无限渲染。 我想将这些变量用作状态。 我希望 totalAmount 成为一个状态变量,其他变量需要成为状态(折扣小计等)。 有什么解决办法。
App.js
import { useState, useEffect } from 'react';
import './styles.css';
function App() {
let order = [
{
qty: 2,
name: 'Margarita A',
variant: 'crab & cucumber',
price: '412.00',
}
];
let [discount, setDiscount] = useState(759.5),
[deliveryFee, setDeliveryFee] = useState(12.0),
[taxes, setTaxes] = useState(46.15),
[subtotal, setSubtotal] = useState(0),
[totalAmount, setTotalAmount] = useState(0);
useEffect(() => {
setTotalAmount(subtotal - discount + deliveryFee + taxes);
}, [subtotal, discount, deliveryFee, taxes]);
return (
<div className="app">
<div className="container">
<div className="orderItems">
{order.map((item, i) => {
// subtotal += +item.price;
setSubtotal((prev) => prev + +item.price);
return (
<div className="orderItem" key={i}>
<span className="orderItemPrice">₹{item.price}</span>
</div>
);
})}
</div>
</div>
<div className="summary">
<span className="summaryTitle">Summary</span>
<div className="total amountBox">
<span>Total</span>
<span>₹ {totalAmount}</span>
</div>
</div>
</div>
<div className="placeOrder">
<button onClick={(e, totalAmount) => {}}>PLACE ORDER</button>
</div>
</div>
);
}
export default App;
问题
问题不在于您的 useEffect
挂钩,它工作正常并在组件挂载时调用一次。问题出在 return
方法中的 setSubtotal((prev) => prev + +item.price);
。
状态变量的每次更改都会导致重新渲染,每次重新渲染都会重新创建您的 order.map
。因此在 order.map
期间更改状态将导致重新渲染,而重新渲染会导致 order.map
再次绘制。这是无限重新渲染的原因。
注意: 您可以简单地在 map
函数中注释 setState
来阻止这种行为。
解决方案
有一些选项可以控制这种情况,例如对 subtotal
使用 useRef
来防止重新渲染的原因。
此外,您可以在计算 totalAmount
和设置它之前在 useEffect
钩子中计算 subtotal
。
function App() {
let order = [
{
qty: 2,
name: "Margarita A",
variant: "crab & cucumber",
price: "412.00"
}
];
const [discount, setDiscount] = useState(59.5);
const [deliveryFee, setDeliveryFee] = useState(12.0);
const [taxes, setTaxes] = useState(46.15);
const [subtotal, setSubtotal] = useState(0);
const [totalAmount, setTotalAmount] = useState(0);
useEffect(() => {
const localSubtotal = order.reduce(
(acc, curr) => (acc += Number(curr.price)),
0
);
setSubtotal(localSubtotal);
setTotalAmount(localSubtotal - discount + deliveryFee + taxes);
}, [discount, deliveryFee, taxes, order]);
return (
<div className="app">
<div className="container">
<div className="orderItems">
{order.map((item, i) => {
return (
<div className="orderItem" key={i}>
<span className="orderItemPrice">₹{item.price}</span>
</div>
);
})}
</div>
</div>
<div>
<div className="summary">
<div>
<span>Sub Total: {subtotal}</span>
</div>
<span className="summaryTitle">Summary</span>
<div className="total amountBox">
<span>Total</span>
<span>₹ {totalAmount}</span>
</div>
</div>
</div>
<div className="placeOrder">
<button onClick={(e, totalAmount) => {}}>PLACE ORDER</button>
</div>
</div>
);
}
export default App;
注意:不要忘记在useEffect
hook的依赖数组中传递order
数组。