React模态框点击外部无法关闭且报ref非prop错误如何解决?
问题根因
- 你使用forwardRef包裹的Layout组件,错误读取
props.ref而非使用forwardRef传入的第二个ref参数,React会自动将ref属性从组件props中剥离,因此props.ref始终为undefined,导致ref无法正确绑定DOM元素,控制台抛出ref相关警告,同时打印的ref.current为null。 useOutsideAlerter自定义Hook定义在Modal组件外部,内部直接访问外部作用域的props无法获取到Modal组件传入的handleClose方法。
需要修改的内容
1. 修正Layout.js的ref绑定
找到Layout组件中div的ref属性,将ref={props.ref}替换为ref={ref},修改后对应代码片段如下:
export const Layout = forwardRef((props, ref) => { return ( <> <div className={props.className} data-tip={props.dataTip} hidden={props.hidden} id={props.id} onClick={props.onClick} onScroll={props.onScroll} onFocus={props.onFocus} onMouseEnter={props.onMouseEnter} onMouseLeave={props.onMouseLeave} onBlur={props.onBlur} ref={ref} // 这里修改为使用forwardRef传入的ref参数 tabIndex={props.tabIndex} target={props.target} style={{/* 原有样式保持不变 */}} > {props.children} </div> </> ); });
2. 修正Modal.js的useOutsideAlerter逻辑
给useOutsideAlerter新增handleClose入参,替换内部的props.handleClose调用,同时把handleClose加入useEffect依赖项,调用Hook时传入Modal组件的props.handleClose,修改后对应代码片段如下:
// 新增handleClose作为入参 function useOutsideAlerter(ref, handleClose) { useEffect(() => { console.log("ref:", ref); function handleClickOutside(event) { console.log("clicking outside 1 | e:" + event.target + " | ref:", ref); if (ref.current && !ref.current.contains(event.target)) { console.log("clicking outside 2"); handleClose(); // 直接使用入参传入的关闭方法 } } document.addEventListener("mousedown", handleClickOutside); return () => { document.removeEventListener("mousedown", handleClickOutside); }; }, [ref, handleClose]); // 新增handleClose到依赖数组 } export const Modal = (props) => { const ref = useRef(null); // 调用Hook时传入handleClose useOutsideAlerter(ref, props.handleClose); // 其余return部分代码保持不变 return (/* 原有结构不变 */) }
效果验证
修改完成后,ref会正确绑定到ModalInner内部的DOM节点,点击模态框外部区域时会正确触发handleClose关闭模态框,控制台的ref相关警告也会同步消失。
内容的提问来源于stack exchange,提问作者Dr J
相关产品推荐
相关产品推荐

