Reactjs 当底层组件重新渲染时,为什么popper会跳到左上角?
我正在使用MaterialUIPopper组件(它反过来使用Popper.js)创建一个悬停工具栏。除了一个奇怪的行为外,它在大多数情况下运行良好:Reactjs 当底层组件重新渲染时,为什么popper会跳到左上角?,reactjs,material-ui,use-effect,popper.js,slate.js,Reactjs,Material Ui,Use Effect,Popper.js,Slate.js,我正在使用MaterialUIPopper组件(它反过来使用Popper.js)创建一个悬停工具栏。除了一个奇怪的行为外,它在大多数情况下运行良好: 选择一些文本:悬停工具栏显示在文本上方-如预期的那样 选择工具栏中的任意按钮:执行相应的操作。但是,工具栏会跳到窗口的左上角。见下文 您可以在中尝试此行为-只需选择一些文本并单击其中一个“T”按钮 基本问题围绕提升器的定位: 当用户选择一些文本时,将创建一个伪虚拟元素,并将其作为锚元素传递给popper。Popper使用此anchorEl定位悬停
anchorEl
定位悬停工具栏。到目前为止还不错useffect()
中。我已确保useffect
的依赖项列表是准确的。我可以看到,当工具栏跳转时,useffect()
没有被调用,这意味着ancorel
没有被重新计算。这让我相信工具栏应该在当前位置保持不变,而不是跳转到(0,0)。但事实并非如此:-(
以下是工具栏组件中的useffect()
代码。您可以在中找到完整的代码。如有任何帮助,将不胜感激
useEffect(() => {
if (editMode === 'toolbar') {
if (isTextSelected) {
const domSelection = window.getSelection();
if (domSelection === null || domSelection.rangeCount === 0) {
return;
}
const domRange = domSelection.getRangeAt(0);
const rect = domRange.getBoundingClientRect();
setAnchorEl({
clientWidth: rect.width,
clientHeight: rect.height,
getBoundingClientRect: () =>
domRange.getBoundingClientRect(),
});
setToolbarOpen(true);
} else {
setToolbarOpen(false);
}
} else {
setToolbarOpen(false);
}
}, [editMode, isTextSelected, selection, selectionStr]);
我相信您的
domRange
在完成其工作后不再有效(因为dom节点被替换),因此getBoundingClientRect
不再返回任何有意义的内容
您应该能够通过在主播的getBoundingClientRect
中重新获取范围来修复此问题。可能类似于以下内容(我没有尝试执行它,因此不能保证没有小错误):
你搞定了,瑞恩!现在很有魅力。非常感谢!
const getSelectionRange = () => {
const domSelection = window.getSelection();
if (domSelection === null || domSelection.rangeCount === 0) {
return null;
}
return domSelection.getRangeAt(0);
};
useEffect(() => {
if (editMode === "toolbar") {
if (isTextSelected) {
const domRange = getSelectionRange();
if (domRange === null) {
return;
}
const rect = domRange.getBoundingClientRect();
setAnchorEl({
clientWidth: rect.width,
clientHeight: rect.height,
getBoundingClientRect: () => {
const innerDomRange = getSelectionRange();
return innerDomRange === null
? null
: innerDomRange.getBoundingClientRect();
}
});
setToolbarOpen(true);
} else {
setToolbarOpen(false);
}
} else {
setToolbarOpen(false);
}
}, [editMode, isTextSelected, selection, selectionStr]);