React DnD useDrag的canDrag属性不生效,拖拽条件控制异常求助
React DnD useDrag canDrag 属性不生效问题修复
问题场景
我需要在 props 中的 flag 变量大于等于 3 时,让组件支持拖拽。使用 React DnD 的 useDrag 钩子并配置了 canDrag 属性,但该属性未生效:
- 代码中计算的
isDrag变量输出值正确,完全符合flag >= 3的判断逻辑 - 若将
canDrag设为!isDrag,仅当flag为默认值 0 时拖拽生效,其他情况均失效
原代码:
const [{ isDragging }, drag] = useDrag(() => { const isDrag = flag >= 3; console.log(isDrag); // 此处输出值正确 return { type: ItemTypes.GAME, item: { id: `${row}_${col}`, row: row, col: col }, options: { dropEffect: "copy", }, collect: (monitor: DragSourceMonitor) => ({ isDragging: monitor.isDragging(), }), canDrag: isDrag, }; }, [flag, row, col]); // 后续渲染代码... const highlight = row == minDelta.row && col == minDelta.col ? `3px solid red` : `3px solid #e6e6e6`; const tileColor = `rgb(${color.join(", ")})`; return ( <Grid item xs> <StyledGridCell ref={drag} tilecolor={tileColor} highlight={highlight} title={tileColor} /> </Grid> );
解决方案
问题出在 canDrag 的赋值方式上。直接传递布尔值时,React DnD 可能无法在 flag 变化时实时更新拖拽权限判断。正确的做法是将 canDrag 定义为函数,让它每次判断拖拽状态时都能获取最新的 flag 值:
修正后的代码(简洁版)
const [{ isDragging }, drag] = useDrag(() => ({ type: ItemTypes.GAME, item: { id: `${row}_${col}`, row: row, col: col }, options: { dropEffect: "copy", }, collect: (monitor: DragSourceMonitor) => ({ isDragging: monitor.isDragging(), }), // 改为函数形式,实时判断最新的flag值 canDrag: () => flag >= 3, }), [flag, row, col]); // 后续渲染代码不变...
保留日志输出的版本
如果需要保留 isDrag 的日志打印,也可以这样写:
const [{ isDragging }, drag] = useDrag(() => { const isDrag = flag >= 3; console.log(isDrag); return { type: ItemTypes.GAME, item: { id: `${row}_${col}`, row: row, col: col }, options: { dropEffect: "copy", }, collect: (monitor: DragSourceMonitor) => ({ isDragging: monitor.isDragging(), }), // 用函数返回当前计算的isDrag值 canDrag: () => isDrag, }; }, [flag, row, col]); // 后续渲染代码不变...
原因说明
- 当
canDrag是函数时,React DnD 会在每次尝试拖拽时调用该函数,确保获取最新的状态值 - 直接传递布尔值时,只有在
useDrag的工厂函数重新执行(依赖变化)时才会更新,但可能存在状态同步延迟,导致判断逻辑不生效
内容的提问来源于stack exchange,提问作者Ammar Hayder Khan
相关产品推荐
相关产品推荐

