reactjs - 当用户使用 react 和 typescript 拖出拖动区域时,如何正确设置拖动状态?
问题描述
我希望能够将文件拖放到 DropZone div 中。当用户拖入或拖出 DropZone div 时,我希望 DropZone div 的背景颜色为灰色。
下面是我的代码,
function MainComponent () {
return (
<Wrapper>
<SomeOtheComponent/>
<DragAndDrop>
<ListContent> //this is the children for the DragAndDrop component and want this to
//render within DragAndDrop component
{condition_true && (
<FirstList/>
)}
{condition_true && (
<SecondList/>
)}
</ListContent>
</Wrapper>
);
}
const DragAndDrop: React.FC = ({ children }) => { //here i am passing children
const [dragging, setDragging] = useState(false);
const [dragCounter, setDragCounter] = useState(0);
React.useEffect(() => {
// componentDidMount()
setDragCounter(0);
}, []);
const handleDrag = (e: any) => {
e.preventDefault();
e.stopPropagation();
};
const handleDragIn = (e: any) => {
e.preventDefault();
e.stopPropagation();
setDragCounter((prev: number) => prev + 1);
if (e.dataTransfer.files) {
setDragging(true);
}
};
const handleDragOut = (e: any) => {
e.preventDefault();
e.stopPropagation();
setDragCounter((prev: number) => prev - 1);
if (dragCounter === 0) {
setDragging(false);
}
};
const handleDrop = (e: any) => {
e.preventDefault();
e.stopPropagation();
setDragging(false);
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
e.dataTransfer.clearData();
setDragCounter(0);
}
};
return (
<DropZone //this is a styled component div and dropzone area where user can drop files
onDragEnter={handleDragIn}
dragging={dragging}
onDragLeave={handleDragOut}
onDragOver={handleDrag}
onDrop={handleDrop}
>
);
};
但是现在这工作正常,当用户将文件拖到 dropzone div 拖动状态为 true 时,现在如果用户将文件拖出 dropzone div(即 handleDragOut),则拖动状态仍然为 true。
它应该是错误的......我也不确定我是否设置正确的拖动计数器值或需要。
有人可以帮我解决这个问题。谢谢。
解决方案
您的handleDragOut
处理程序检查是否dragCounter
为零,但此状态尚未更新。
这是一个更新的版本:
const handleDragOut = (e: any) => {
e.preventDefault();
e.stopPropagation();
setDragCounter((prev: number) => prev - 1);
if (dragCounter > 1) return;
setDragging(false);
};
并且handleDrop
应该重置计数器,无论:
const handleDrop = (e) => {
e.preventDefault();
e.stopPropagation();
setDragging(false);
setDragCounter(0);
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
e.dataTransfer.clearData();
}
};
在我看来,更清洁的解决方案是useRef
用于柜台。这样,计数器更新不会导致不必要的渲染,并且计数器在递增/递减后立即更新。
这是一个例子:
const DragAndDrop = ({ onUpload, children }) => {
const [isDragging, setIsDragging] = React.useState(false);
const dragCount = React.useRef(0);
const handleDragIn = (e) => {
e.preventDefault();
e.stopPropagation();
dragCount.current++;
setIsDragging(true);
};
const handleDrag = (e) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(true);
};
const handleDragOut = (e) => {
e.preventDefault();
e.stopPropagation();
dragCount.current--;
if (dragCount.current > 0) return;
setIsDragging(false);
};
const handleDrop = (e) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
dragCount.current = 0;
const dt = e.dataTransfer;
const files = dt.files; // FileList
// Handle files ...
};
return (
<div
style={{ backgroundColor: isDragging ? 'red' : 'gray', padding: '20px'}}
onDragEnter={handleDragIn}
onDragOver={handleDrag}
onDragLeave={handleDragOut}
onDrop={handleDrop}
>
Drag here
<div>A nested div</div>
</div>
);
};
在您的情况下,不是渲染 a ,而是像以前那样div
渲染样式化的组件。DropZone
推荐阅读
- angular - angular 的选择模型如何确定两个对象的相等性?
- spring - 从 Windows 域外访问授权服务器时如何禁用登录弹出窗口?
- wordpress - 如何为网站的前 100 位先到用户设置并提供 Memberpress 插件免费注册?
- oracle - Oracle“pl/sql”集合是按值分配还是按引用分配?
- flutter - 方法未在其他类中定义
- html - 延迟按钮动画 CSS
- python - 有没有更好的方法来使用 Python 的类型模块为复合类型创建类型别名?
- c++ - C++ 表达式值类别在 C++ 之外是否相关?
- c# - 如何让 CreatedAtAction 添加查询参数?
- java - 无法运行 Oracle 提供的 Doclet 类