我有一个网格可以呈现可变高度的卡片。
为了获得卡片的高度,我将卡片包裹在ReactHeight
(https://github.com/nkbt/react-height)中,这样我就可以在高度准备就绪时将回调函数传递给它。
我将卡片高度保留在组件state
中的一个数组中,我会在报告卡片高度时更新。
当所有高度都可用时,我会从高度计算填充,render
传递给卡
在简化版中,它看起来像这样。
class Grid extends Component {
constructor() {
...
this.state = { cardHeights: {}, paddings: [] }; //initial state
}
componentDidUpdate() {
const i = setInterval(() => {
if (all heights are ready) {
// ...calculate paddings
this.setState(paddings: calculatedPaddings);
clearInterval(i);
}
}, 100);
// *A*
}
updateCardHeights(index, height) {
this.setState(prevState => ({
cardHeights: {
...prevState.cardHeights,
[index]: height,
},
}));
}
render() {
// index = cards are indexed like 1 2 3
// 4 5 6
// 7 8 9
// 10 11 12
// ...
return (
<ReactHeight onHeightReady={ height => this.updateCardHeights(index, height) }
<Card padding={this.state.paddings[index]}/>
</ReactHeight>
);
}
}
我知道setState()
调用render
,调用函数变异render
内的状态通常会导致无限循环。
在我的代码中,render
调用更新this.state.cardHeights
数组的函数,其子组件Card
的呈现间接取决于this.state.cardHeights
,因为this.state.paddings
直接依赖的1}}是基于componentDidUpdate()
上的cardHeights计算的。
但是,我无法在不渲染的情况下获得Card
组件的高度,因此我能想到的唯一方法是使padding
成为卡片的prop
和组件的状态,然后在渲染后更改状态。
我的问题是:
不管怎么说,即使我在渲染中改变状态,我的代码也没有导致无限循环,但这是一种更好的方法吗?
clearInterval()
函数中的 componentDidUpdate()
似乎不起作用。我在*A*
部分放了一个print语句,即使满足if条件并且假定调用了clearInterval()
,它也会保持打印。这可能是因为我的状态突变吗?
答案 0 :(得分:3)
在这种情况下,您应该在更新状态之前检查先前的值和新值是否相同。我希望每个渲染的高度不会更新。因此,您可以检查updateCardheights
以确定是否存在实际更改,然后更新状态。这可确保它不会更新冗余更新的状态。但是如果在每个渲染中你的状态将会更新,那么问题将保持不变。
updateCardHeights(index, height) {
if(this.state.cardHeights[index] !== height) {
this.setState(prevState => ({
cardHeights: {
...prevState.cardHeights,
[index]: height,
},
}));
}
}
答案 1 :(得分:-2)
我对以上问题有以下解决方案。 只需在render函数之外分配事件处理程序。并且不要忘记在构造函数中绑定您的事件处理程序。之后,您可以在渲染函数中调用该事件处理程序