因此,我遇到了这个问题,在过去的几天里,我的脑袋一直碰壁,那里有一个简单的表格,可能有多个div和四个输入,但它们彼此相关。我想做的是计算div值中的最后一个输入,该值基于其余输入的值并被动态键入,然后输入setState()
以返回新状态。我有处理程序功能(用于添加,删除或更改输入字段的值),该功能在我不需要处理此特定更新时可以工作。现在是代码:
class App extends React.Component {
state = {
bank: 10,
totalPrice: 0,
hands: [
{
name: "hand1",
backPrice: 0,
bankPrice: 0,
commision: 0,
realPrice: 0
}
],
handCount: 1
};
componentDidUpdate(prevProps, prevState) {
const hands = this.state.hands;
// initialized variables needed to calculate a result
const totalPrice = hands.reduce((total, hand) => {
return (hand.backPrice || 1) * total;
}, 1);
// lastHandPrice is ALWAYS needed, it is the base of the rest of calculations
const lastHandPrice = (this.state.bank * totalPrice) /
(hands[hands.length - 1].bankPrice -
(hands[hands.length - 1].commision / 100));
const newHands = hands.reduceRight(
// calculation starts in reverse, with the first value being lastHandPrice
// it returns an array of number values reversed again to be in correct order
(newHands, hand, ind, array) => {
let prevHand = array[ind + 1];
let prevPrice = newHands[array.length - ind - 2];
if (hand == array[array.length - 1]) {
return newHands.concat(lastHandPrice)
} else {
return newHands.concat(
prevPrice * (1 - (prevHand.commision / 100)) /
(hand.bankPrice - (hand.commision / 100))
)
}
}, []
).reverse();
if (this.state.hands !== prevState.hands)
this.setState({
totalPrice: totalPrice,
hands: this.state.hands.map((hand, index) => {
return Object.assign(hand, {realPrice: newHands[index]})
})
})
}
div中有四个主要输入字段,以state.hands
表示。
因此,这段代码在我的终端机上工作得很完美,但是当我尝试以下操作时,响应会引发Maximum update depth exceeded
错误:
向数组添加新手
尝试在输入中输入任何内容
我对此无能为力。我尝试了其他几种方法来实现此目的,但始终会遇到相同的错误。似乎某种循环开始起作用,但我无法弄清楚。为什么不让我更新state.hands
?
输入更改/添加/或删除处理程序非常可预测,只需更新所需的值,添加四个输入字段的div,然后删除所选的div。要在map()
上更改值state.hands
,然后再将Object.assign()
的属性值更改为所需的对象(hand1,hand2等)。
编辑(其余代码):
handleInputChange = (event) => {
const handName = event.currentTarget.parentNode.getAttribute("name");
const handInput = event.currentTarget.getAttribute("name");
const value = event.currentTarget.value;
if (handInput === "bank" || handInput === "totalPrice") {
this.setState({
[handInput]: value
});
} else {
this.setState(prevState => ({
hands: prevState.hands.map(
hand => {
if (hand.name === handName) {
return Object.assign(hand, { [handInput]: value })
} else {
return hand
}
}),
}));
}
}
handleAddHand = () => {
const handCount = this.state.handCount;
const name = `hand${handCount + 1}`;
const hand = {
name,
backPrice: 0,
bankPrice: 0,
commision: 0,
realPrice: 0
};
this.setState(prevState => ({
hands: prevState.hands.concat({...hand}),
handCount: prevState.handCount + 1
})
);
}
handleRemoveHand = (event) => {
const handName = event.currentTarget.parentNode.getAttribute("name");
const handIndex = this.state.hands.findIndex(hand =>
hand.name === handName);
this.setState(prevState => ({
hands: [
...prevState.hands.slice(0, handIndex),
...prevState.hands.slice(handIndex + 1)
]
}));
}
render() {
const listHands = this.state.hands
.map(hand =>
<HandInputs
key={hand.name}
name={hand.name}
backPrice={hand.backPrice}
bankPrice={hand.bankPrice}
commision={hand.commision}
realPrice={hand.realPrice}
handleChange={this.handleInputChange}
removeHand={this.handleRemoveHand}
/>
);
return (
<div>
<input
name="bank"
value={this.state.bank}
onChange={this.handleInputChange}
/>
<input
name="totalPrice"
value={this.state.totalPrice}
onChange={this.handleInputChange}
/>
{listHands}
<button onClick={this.handleAddHand}>Add Hand</button>
</div>
);
}
function HandInputs(props) {
return (
<div name={props.name}>
<input type="text" value={props.backPrice}
name="backPrice" onChange={props.handleChange} />
<input type="text" value={props.bankPrice}
name="bankPrice" onChange={props.handleChange} />
<input type="text" value={props.commision}
name="commision" onChange={props.handleChange} />
<input type="text" value={props.realPrice}
name="realPrice" onChange={props.handleChange} />
{props.name !== "hand1" &&
<button onClick={props.removeLeg}>Remove leg</button>}
</div>
);
}
答案 0 :(得分:0)
因为您在setState
中调用了componentDidUpdate
,所以该组件再次经历了更新生命周期,并循环调用了componentDidUpdate
。
您的支票:if (this.state.hands !== prevState.hands)
将始终为true
,因为您始终在状态下创建一个新的hands
数组:
this.setState({
totalPrice: totalPrice,
hands: this.state.hands.map((hand, index) => { <-- always cause a new array
return Object.assign(hand, {realPrice: newHands[index]})
})
})
一个解决方案是使用callback
函数作为setState
的第二个参数。状态更改后将调用此回调,并且您可以在其中使用state
,就像在componentDidUpdate
中使用它一样。
// the same function as your componentDidUpdate
afterStateChange = () => {
const hands = this.state.hands;
// initialized variables needed to calculate a result
...
// you can call `setState` here (you don't need to check if the state is different from prevState
this.setState({
totalPrice: totalPrice,
hands: this.state.hands.map((hand, index) => {
return Object.assign(hand, { realPrice: newHands[index] });
})
});
然后例如您可以在这里使用它:
handleAddHand = () => {
const handCount = this.state.handCount;
const name = `hand${handCount + 1}`;
const hand = {
name,
backPrice: 0,
bankPrice: 0,
commision: 0,
realPrice: 0
};
this.setState(
prevState => ({
hands: prevState.hands.concat({ ...hand }),
handCount: prevState.handCount + 1
}),
this.afterStateChange <-- here
);
};