ReactJS使用useState存储锚点DOM元素时出现无效锚点问题
问题原因及解决方案
原因分析
这个问题核心在于React的重渲染机制:
- 调用
setForm更新组件状态时,会触发组件重新渲染。 - 重渲染过程中,原
<StyledHeader>对应的DOM元素可能被销毁并重新创建(或因虚拟DOM diff被替换)。 - 你存在状态里的
event.currentTarget是重渲染前的旧DOM节点引用,该节点已被React从页面移除,因此控制台提示“Node cannot be found in the current page”。 - 额外提一句:React的事件对象是池化复用的,事件处理完成后属性会被清空,但这里的核心矛盾还是重渲染导致的DOM节点失效。
解决方案
推荐两种可行处理方式:
1. 使用useRef存储DOM引用(更推荐)
不要通过事件对象获取DOM,直接给目标组件绑定ref,拿到稳定的DOM引用,不会因重渲染失效:
import { useRef } from 'react'; // 组件内定义ref const headerRef = useRef(null); // 修改StyledHeader的绑定 <StyledHeader ref={headerRef} avatar={ <Avatar className="md:mx-4" alt="user photo" src={user.data.photoURL} /> } title={row.commentUser} onMouseEnter={(ev) => { ev.preventDefault(); handlePopup(row.id); }} /> // 修改handlePopup函数 function handlePopup(id) { if (headerRef.current) { console.log(headerRef.current); setForm({ anchor: headerRef.current, id: id }); } }
注意:如果<StyledHeader>是自定义组件,需要用React.forwardRef包裹以转发ref,否则无法直接获取DOM节点。
2. 存储DOM位置信息而非DOM引用
如果仅需锚点位置定位弹窗,可存储元素的位置数据而非DOM本身:
function handlePopup(event, id) { const rect = event.currentTarget.getBoundingClientRect(); // 存储位置信息 setForm({ anchorRect: rect, id: id }); // 后续弹窗定位直接使用rect的top/left等属性即可 }
这种方式避免了存储DOM引用,自然不会出现节点失效问题。
内容的提问来源于stack exchange,提问作者burn_it
相关产品推荐
相关产品推荐

