
在使用 `useref` 获取 dom 元素时,`ref.current` 在组件首次渲染或元素尚未挂载时为 `undefined`,直接访问其属性(如 `offsetwidth`)会抛出 typeerror;需通过可选链操作符或条件判断确保元素存在后再读取。
React 的 useRef 返回的对象在整个组件生命周期中保持不变,但其 .current 属性的值取决于 DOM 元素是否已实际挂载。在你的 Modal 场景中,
✅ 正确做法是:始终校验 ref 是否已挂载。推荐使用可选链操作符(?.)配合空值合并(??)提供默认值,既简洁又健壮:
useEffect(() => {
if (modalRef.current) {
console.log("Modal width:", modalRef.current.offsetWidth);
// ✅ 安全访问:此处 modalRef.current 已挂载
}
}, [modalRef.current]); // 注意:依赖项应为 modalRef.current,而非 modalRef⚠️ 关键注意事项:
- 依赖数组必须写 modalRef.current:仅监听 modalRef 对象本身无意义(它永不变更),只有 modalRef.current 的变化(即 DOM 节点挂载/卸载)才值得响应;
-
避免在 unmountOnExit 下对未挂载节点操作:若需在 Modal 显示后立即计算尺寸,应将逻辑移至 in={true} 状态稳定后的时机,例如结合 CSSTransition 的 onEntered 回调:
{ if (modalRef.current) { const width = modalRef.current.offsetWidth; console.log("Modal fully entered, width:", width); // 此处可安全执行定位逻辑(如 relative to trigger element) } }} > - 定位 Modal 时注意触发元素与 Modal 的时序关系:你已在 toggle() 中打印了 event.target.offsetTop,建议将该偏移量与 modalRef.current 的计算逻辑解耦——先确保 Modal 挂载完成,再读取其尺寸并动态设置 top/left 样式。
总结:useRef 不是魔法,它只是容器;DOM 引用的安全访问永远建立在“存在性校验”之上。结合 onEntered 生命周期钩子 + ?. 可选链,即可稳健实现基于触发元素位置的 Modal 动态定位。










