我有一个网格,可以渲染可变高度的卡片。
为了获取卡片的高度,我将卡片渲染在 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
它直接依赖的是根据componentDidUpdate()
上的cardHeights计算的.
但是,我无法获取 Card
的高度组件而不渲染它,所以我能想到的唯一方法是制作 padding
一个prop
到组件的卡片和状态,然后渲染后改变状态。
我的问题是:
即使我在渲染内更改状态,我的代码也不会导致无限循环,但有更好的方法吗?
clearInterval()
在我的里面componentDidUpdate()
功能似乎不起作用。我在*A*
中放置了一条打印语句部分,即使满足 if 条件并且clearInterval()
,它也会继续打印据说被称为。难道是我状态突变导致的?
最佳答案
在这种情况下,您应该在更新状态之前检查先前的值和新值是否相同。我希望你的高度不会因每次渲染而更新。因此,您可以检查updateCardheights
以确定是否存在实际更改,然后更新状态。这确保它不会更新冗余更新的状态。但如果在每次渲染时您的状态都会更新,那么问题将保持不变。
updateCardHeights(index, height) {
if(this.state.cardHeights[index] !== height) {
this.setState(prevState => ({
cardHeights: {
...prevState.cardHeights,
[index]: height,
},
}));
}
}
关于reactjs - 当状态依赖于 render 时,如何避免 render() 内的 setState(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44037611/