React/Redux拖拽项目中事件未向store派发action问题排查
核心问题原因
- 元素
key使用随机值:每次dispatch action触发状态更新后,组件重渲染会生成新的随机key,React会判定为全新元素,直接卸载原有正在拖拽的元素、创建新元素,直接导致拖拽中断,元素失去可拖拽状态,这是你禁用action就正常、开启就异常的核心诱因。 - 缺失拖拽必填的事件配置:部分浏览器(尤其是Chrome内核浏览器)要求拖拽事件必须在
onDragStart中调用e.dataTransfer.setData()才会判定拖拽有效;同时必须在onDragOver中阻止默认行为,才允许触发onDragEnter等后续拖拽事件。 - 初始状态缺失字段:
InitialState中没有定义createdElements,首次触发DRAGGED_ENDaction时会读取到undefined,调用reArrangeElements会抛出异常,进一步导致渲染异常。 onDragEnter高频触发无拦截:拖拽过程中onDragEnter会高频触发,无判断直接dispatch会导致状态频繁更新,引发频繁重渲染打断拖拽流程。
修复方案
1. 替换随机key为固定唯一值
不要使用随机数作为元素key,替换为和元素强绑定的唯一标识,比如每个组件的自定义id,若没有特殊唯一值可临时用index替代:
// 修改前 key: Math.floor(Math.random() * 1000), // 修改后 key: newComponents[index].id || index,
2. 补充拖拽必填事件配置
在拖拽容器的事件回调中补充必填的配置项:
const _formBuilder = (newComponents, index, remove, draggedItem, enteredItem, dragEnd, currentEntered) => { if (!newComponents.length) return; const divContainer = _creator('div', { key: newComponents[index].id || index, draggable: true, onDragStart: (e) => { // 强制设置dataTransfer,兼容浏览器拖拽规则 e.dataTransfer.setData('text/plain', String(index)); console.log(index); draggedItem(index); }, // 阻止dragover默认行为,允许元素接收拖拽事件 onDragOver: (e) => { e.preventDefault(); }, onDragEnter: (e) => { e.stopPropagation(); // 仅在进入位置变化时才dispatch,避免高频更新 if (index !== currentEntered) { console.log(index); enteredItem(index); } }, onDragEnd: (e) => { console.log(index); dragEnd(); }, }, [ newElement, trash, ]); return divContainer; };
调用_formBuilder时传入当前store中存储的entered值作为currentEntered参数。
3. 补充初始状态缺失字段
在初始状态中添加createdElements的默认值:
const InitialState = { dragged: 0, entered: 0, createdElements: [] }
内容的提问来源于stack exchange,提问作者Mbiplang Ardel
相关产品推荐
相关产品推荐

