Next.js中react-dnd useDrop的monitor.isOver({shallow:true})返回值异常
React Dnd shallow模式下isOver判断失效问题
我的Sidebar组件里有可拖拽元素,拖入工作区前需要判断是悬停在工作区本身还是它的子元素上。根据react-dnd文档,monitor.isOver({shallow: true})应该在悬停元素自身时返回true,子元素时返回false,但实际两种情况都返回true。以下是复现代码,求可行解决办法。
请勿提供AI生成的无效建议,我已经试过很多了
export default function TestC() { const dropRef = useRef(null); const hRef = useRef(null); const [{ isOver, canDrop }, drop] = useDrop(() => ({ accept: ["element", "component"], hover: (item, monitor) => { let a = monitor.isOver({ shallow: true }); console.log(a); }, drop: (item, monitor) => {}, collect: (monitor) => ({ isOver: monitor.isOver({ shallow: true }), canDrop: monitor.canDrop(), }), })); drop(dropRef); return ( <div className="flex justify-around"> <Sidebar /> <div className="w-[600px] h-[2000px] border-2 border-dashed border-amber-500"> <div id="a" data-wb-id="workspace" ref={dropRef} role={`Dustbin`} className={`w-full h-full`} style={{ backgroundColor: isOver ? "green" : "gray", overflow: "auto", }} > <h1 id="b" ref={hRef} className=" border-2 border-orange-400 mb-3"> Test1 </h1> <p id="c" className=""> Test2 </p> </div> </div> </div> ); }
可行解决思路
给子元素添加空drop target拦截
给工作区的子元素(比如示例中的h1、p)单独注册一个不接受任何拖拽类型的drop target,让子元素优先捕获悬停事件,这样父元素的shallow: true判断就能区分自身和子元素。示例修改:// 给h1添加空drop target const [, dropH1] = useDrop(() => ({ accept: [], // 不接受任何拖拽类型 collect: () => ({}), })); dropH1(hRef); // 同理给p也添加 const pRef = useRef(null); const [, dropP] = useDrop(() => ({ accept: [], collect: () => ({}), })); dropP(pRef);手动计算拖拽位置与元素边界
不依赖react-dnd的shallow判断,直接通过坐标计算区分。在hover方法里获取拖拽位置和元素的边界矩形,判断鼠标是否在工作区内但不在子元素范围内:hover: (item, monitor) => { const dropRect = dropRef.current.getBoundingClientRect(); const h1Rect = hRef.current.getBoundingClientRect(); const pRect = document.getElementById('c').getBoundingClientRect(); const { x, y } = monitor.getClientOffset(); // 判断是否仅悬停在工作区自身 const isOverWorkspaceOnly = x >= dropRect.left && x <= dropRect.right && y >= dropRect.top && y <= dropRect.bottom && !(x >= h1Rect.left && x <= h1Rect.right && y >= h1Rect.top && y <= h1Rect.bottom) && !(x >= pRect.left && x <= pRect.right && y >= pRect.top && y <= pRect.bottom); console.log(isOverWorkspaceOnly); },检查版本与配置
确认当前react-dnd版本是否存在shallow模式的已知bug,尝试升级到最新稳定版;同时检查工作区元素的ref是否正确绑定,避免嵌套了其他未预期的drop target。
内容的提问来源于stack exchange,提问作者Tanmoy Sen
相关产品推荐
相关产品推荐

