请考虑以下事项:
带有下拉子菜单系统的简单顶级菜单:
<div id="menuBar">
<div id="menuItemA">
<div ref="refMenuItemA-DropList"
onMouseOut={ this.hideSubMenu.bind(this, this.props.item) }
onMouseOver={ this.showSubMenu.bind(this, this.props.item) }
style={ {
display: this.state.display,
opacity: this.state.opacity,
left: this.state.left,
top: this.state.top,
width: this.state.width
} }>
<div id="subMenuItemA" ref="refSubMenuItem"> SubMenuItem A
<div id="subSubMenuItemA">subSubMenuItemA</div>
.......
.......
</div>
<div id="subMenuItemB"> SubMenuItem B </div>
<div id="subMenuItemC"> SubMenuItem C </div>
</div>
<div>
</div>
在初始渲染时:
this.state = {
opacity: 0,
display: 'none',
bottom: 0,
height: 0,
left: 0,
right: 0,
top: 0,
width: 0,
selected: ''
};
当onMouseOver
事件触发时,我可以轻松确定this.state.top & this.state.left
对refMenuItemA-DropList
的影响,因为其父MenuItemA
始终可见......
我可以检索refMenuItemA-DropList
的参考值,找到它的父母的左边&amp;底部属性并将它们传递给状态;和,
更改&lt; DIV&GT;拥有refMenuItemA-DropList
可见,并且在上面#1中给出了正确定位的左上角。
但我无法确定相同div的宽度,因为它的状态尚未变为可见。
此外,尝试检索&lt; div&gt;的顶部拥有refSubMenuItem
,以及#3中提到的宽度值,并将它们传递给它的子项在同一mouse-over
事件中将是徒劳的,因为状态值在componentDidUpdate
之前不会更新,因此不透明度是仍为0且显示仍为“无”。
问题:
如果状态在componentDidUpdate
之前没有更新,并且我无法在componentDidUpdate
中设置状态,我怎样才能将值传递给子菜单项的子节点,以便一旦状态更新就可以正确对齐使元素可见,因为需要一个可见元素来检索大小/位置值?
答案 0 :(得分:1)
我真的很想过这个。虽然ReactJS的文档强烈建议不要在componentDidUpdate
中搞乱状态,但我研究得越多,就越多人指出没有别的办法了。
我没有收到任何错误,没有警告,应用程序没有缓慢,我有超过100条路线,就像一个旧的骡子我一次又一次地击败应用程序以找到任何退化,但没有。
为了不将您与上述内容混淆,在我的应用中,实际的引用名称不是
refMenuItemA-DropList1 but rather 1refFlyList
所以这是我的解决方案......
予。顶NAV-菜单item.js
componentDidUpdate() {
const self = this;
if (self.refs.refFlyList !== undefined) {
const refFlyList = self.refs.refFlyList.clientWidth;
// need this or endless loop
if (refFlyList === this.state.width) return;
if (refFlyList !== 0) {
this.setState( { width: refFlyList } );
}
}
}
fetchSubMenu(node) {
if (node.childNodes !== undefined) {
const parentDims= {
width: this.state.width,
top: this.state.top,
left: this.state.left
};
return (
node.childNodes.map((childNode, index) => {
return (
<SubMenuItem key={ index }
node={ childNode }
parentDims={ parentDims }
/>
);
})
);
}
}
II。子菜单item.js
showSubMenu(node, event) {
if (node.childNodes !== undefined) {
const parentDims = this.props.parentDims;
if (this.state.top === 0) {
this.setState({
left: parentDims.width,
top: event.clientY - parentDims.top
});
}
this.setState({
opacity: 1,
display: 'block',
selected: ' selected'
});
}
}
III。如果像我一样你使用的是linting helper(我使用EsLint):
"rules": {
"react/no-did-update-set-state": 0,
.....................
我的react-router是动态的[数据来自Mongo],它是递归的。虽然我只能达到3个等级,但是我玩了6个等级,一切都运行良好。
解决方案并不像黑客那样,性能也很棒!