Skip to content

fix: Upload drag & drop not working #625

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 27, 2025
Merged

fix: Upload drag & drop not working #625

merged 2 commits into from
May 27, 2025

Conversation

zombieJ
Copy link
Member

@zombieJ zombieJ commented May 27, 2025

故障原因

#624 中,对存在文件的情况进行 preventDefault 处理。这本对于 Paste 和 Drog 都会有效,但是由于原来的 onFileDropOrPaste 方法其实除了处理 pastedrop 事件外,还处理了 onDragOver 事件。而 onDragOver 事件是没有 files 要处理的,导致其不会触发 preventDefault 逻辑。

当文件拖拽不处理 dragOverpreventDefault 时,drop 也会被浏览器忽略。

此外,测试用例中也仅仅做了 drop 事件的测试,而没有做 dragOver 测试导致 preventDefault 逃逸。

修复方式

重构了这部分代码,将三个事件拆分成独立的函数进行分别处理。对于相同逻辑处,提取 onDataTransferFiles 抽象逻辑。

Summary by CodeRabbit

  • 重构
    • 优化了文件拖拽和粘贴上传的事件处理逻辑,提升了代码可读性和维护性。
  • 测试
    • 增强了拖拽上传目录的测试用例,确保在拖拽经过时会正确阻止浏览器默认行为。

Copy link

vercel bot commented May 27, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
upload ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 27, 2025 2:41pm

Copy link

coderabbitai bot commented May 27, 2025

Walkthrough

此次更改将原有的文件拖拽和粘贴事件处理逻辑进行重构,将原本合并的 onFileDropOrPaste 方法拆分为更专注的独立方法。新增了 onDataTransferFiles 用于统一处理文件提取和上传,分别为粘贴、拖拽悬停和拖拽释放事件编写了独立的处理函数,并相应地调整了生命周期方法与事件监听注册。测试用例也增加了对拖拽悬停时 preventDefault 调用的断言。

Changes

文件/分组 变更摘要
src/AjaxUploader.tsx 拆分并重构文件输入事件处理逻辑,移除 onFileDropOrPaste,新增 onDataTransferFilesonFilePasteonFileDragOveronFileDrop 方法,更新事件监听注册与生命周期方法。
tests/uploader.spec.tsx 增加对 dragOver 事件中 preventDefault 调用的断言,完善异步目录上传相关测试。

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DOM
    participant AjaxUploader
    participant UploadLogic

    User->>DOM: 拖拽文件/粘贴文件
    DOM->>AjaxUploader: 触发 onFileDrop/onFilePaste/onFileDragOver
    AjaxUploader->>AjaxUploader: onFileDragOver (仅阻止默认)
    AjaxUploader->>AjaxUploader: onFileDrop/onFilePaste
    AjaxUploader->>AjaxUploader: onDataTransferFiles(dataTransfer)
    AjaxUploader->>UploadLogic: 处理文件/目录、过滤、上传
Loading

Possibly related PRs

Poem

🐇
拖拽一片云,粘贴一缕风,
事件分明,逻辑更通。
preventDefault 不再迷路,
上传之旅,兔子守护。
代码重构,清晰如初!

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

tests/uploader.spec.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "prettier" to extend from. Please check that the name of the config is correct.

The config "prettier" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

src/AjaxUploader.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "prettier" to extend from. Please check that the name of the config is correct.

The config "prettier" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

codecov bot commented May 27, 2025

Codecov Report

Attention: Patch coverage is 86.36364% with 3 lines in your changes missing coverage. Please review.

Project coverage is 89.10%. Comparing base (746ab3c) to head (8d58b89).

Files with missing lines Patch % Lines
src/AjaxUploader.tsx 86.36% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #625      +/-   ##
==========================================
+ Coverage   89.07%   89.10%   +0.03%     
==========================================
  Files           6        6              
  Lines         302      303       +1     
  Branches       87       80       -7     
==========================================
+ Hits          269      270       +1     
  Misses         33       33              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@zombieJ zombieJ merged commit dfaea1b into master May 27, 2025
8 of 10 checks passed
@zombieJ zombieJ deleted the fix-drop branch May 27, 2025 14:45
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/AjaxUploader.tsx (3)

95-108: 粘贴事件处理器逻辑正确,但建议简化条件检查。

方法正确处理了粘贴事件并调用了统一的文件处理逻辑。

考虑简化条件检查,因为方法名已经表明了它的用途:

-  if (e.type === 'paste') {
-    const clipboardData = (e as ClipboardEvent).clipboardData;
-    return this.onDataTransferFiles(clipboardData, () => {
-      e.preventDefault();
-    });
-  }
+  const clipboardData = e.clipboardData;
+  return this.onDataTransferFiles(clipboardData, () => {
+    e.preventDefault();
+  });

114-122: 拖拽释放处理器设计合理,但建议简化条件检查。

方法正确处理了拖拽释放事件并防止了默认行为。

类似于粘贴处理器,可以简化条件检查:

-  if (e.type === 'drop') {
-    const dataTransfer = (e as React.DragEvent<HTMLDivElement>).dataTransfer;
-
-    return this.onDataTransferFiles(dataTransfer);
-  }
+  const dataTransfer = e.dataTransfer;
+  return this.onDataTransferFiles(dataTransfer);

130-130: 事件监听器绑定更新正确,但可以优化内存管理。

事件监听器的添加和移除逻辑正确,符合 React 生命周期最佳实践。

根据检索到的学习记录,考虑使用预绑定的方法而不是 .bind(this) 来避免潜在的内存泄漏。当前实现已经很好地使用了预绑定的方法(this.onFilePaste),这是正确的做法。

另外,建议在 componentWillUnmount 中添加条件检查:

  componentWillUnmount() {
    this._isMounted = false;
    this.abort();
-   document.removeEventListener('paste', this.onFilePaste);
+   if (this.props.pastable) {
+     document.removeEventListener('paste', this.onFilePaste);
+   }
  }

Also applies to: 137-137, 144-144, 146-146

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 746ab3c and 8d58b89.

📒 Files selected for processing (2)
  • src/AjaxUploader.tsx (4 hunks)
  • tests/uploader.spec.tsx (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/AjaxUploader.tsx (1)
Learnt from: zombieJ
PR: react-component/upload#543
File: src/AjaxUploader.tsx:116-116
Timestamp: 2025-04-09T06:22:00.335Z
Learning: 在 react-component/upload 项目中,黏贴上传功能应该是可配置的,只有当启用此功能时才应添加 paste 事件监听器,而不是无条件添加。同时,事件监听器绑定应使用预先绑定的方法而非直接使用 .bind(this) 以避免内存泄漏。
🔇 Additional comments (4)
tests/uploader.spec.tsx (1)

738-754: 测试增强很好地验证了 preventDefault 的调用。

这个测试补充完美地配合了代码重构,确保 dragOver 事件期间正确调用 preventDefault。测试结构清晰,使用了适当的 spy 模式来验证方法调用,并在断言后正确恢复了 spy。

src/AjaxUploader.tsx (3)

69-93: 新的 onDataTransferFiles 方法设计良好,提供了统一的文件处理逻辑。

这个方法很好地统一了粘贴、拖拽等事件的文件处理逻辑,支持目录和单文件上传,并正确处理文件过滤和多文件限制。使用可选的 existFileCallback 参数允许调用者在检测到文件时执行特定操作(如调用 preventDefault)。


110-112: 拖拽悬停处理器完美解决了原始问题。

这个简单但关键的方法通过在 dragOver 事件期间调用 preventDefault 解决了拖拽上传不工作的核心问题。实现简洁明了。


346-347: 事件属性绑定正确更新以匹配新的方法结构。

onDroponDragOver 绑定到新的专用方法是正确的,确保了拖拽功能的正常工作。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant