improve upload state handlers ergonomics#5843
Conversation
There was a problem hiding this comment.
Greptile Overview
Summary
This PR improves the developer experience for upload components by implementing automatic injection of the `upload_files` function call when users provide bare event handlers. The change allows developers to write more concise upload handlers like `on_drop=State.on_upload` instead of the more verbose `on_drop=State.on_upload(rx.upload_files("upload"))`.The implementation works by detecting when an EventHandler is provided to the on_drop parameter and automatically wrapping it with the appropriate upload_files(upload_id) call. This is achieved through modifications to the Upload.create() method in reflex/components/core/upload.py, which now iterates through on_drop events and performs the injection when needed.
Additionally, the PR includes a lazy loading optimization in reflex/app.py by moving upload-related imports from module-level to inside the _add_optional_endpoints() method where they are actually used. This reduces startup overhead for applications that don't use upload functionality.
The changes maintain full backward compatibility - existing code that already passes rx.upload_files() explicitly will continue to work unchanged, while new code can take advantage of the simplified syntax. The type stub hash update in pyi_hashes.json ensures type checking tools recognize the updated interface signatures.
Changed Files
| Filename | Score | Overview |
|---|---|---|
| reflex/app.py | 5/5 | Moved upload imports to lazy load inside _add_optional_endpoints() method for startup optimization |
| pyi_hashes.json | 5/5 | Updated hash for upload.pyi file to reflect type stub changes |
| reflex/components/core/upload.py | 4/5 | Added automatic injection of upload_files() call for bare event handlers and improved event specification |
Confidence score: 4/5
- This PR is safe to merge with minimal risk as it maintains backward compatibility while improving developer ergonomics
- Score reflects solid implementation with good defensive programming, though the automatic injection logic adds some complexity
- Pay close attention to
reflex/components/core/upload.pyfor the event handler injection logic
Sequence Diagram
sequenceDiagram
participant User
participant Frontend
participant Backend
participant Upload Component
participant Event System
Note over User,Event System: PR: Improve Upload State Handlers Ergonomics
User->>Frontend: "Creates rx.upload component with on_drop=State.on_upload"
Frontend->>Upload Component: "Upload.create() called during compilation"
Upload Component->>Upload Component: "Check if on_drop handler provided"
alt on_drop handler is bare EventHandler
Upload Component->>Upload Component: "Detect bare EventHandler without upload_files"
Upload Component->>Event System: "Wrap handler with upload_files(upload_id)"
Note right of Event System: Before: State.on_upload<br/>After: State.on_upload(rx.upload_files("upload"))
Event System->>Upload Component: "Return enhanced EventSpec"
else on_drop handler already has args
Upload Component->>Upload Component: "Use handler as-is"
end
Upload Component->>Upload Component: "_update_arg_tuple_for_on_drop() processes args"
Upload Component->>Frontend: "Return configured upload component"
Note over User,Event System: Runtime: File Upload Flow
User->>Frontend: "Drops files on upload component"
Frontend->>Backend: "Trigger on_drop event with upload_files payload"
Backend->>Event System: "Process event with enhanced handler"
Event System->>Backend: "Execute State.on_upload with file list"
Backend->>Frontend: "Return state update"
Frontend->>User: "Update UI with upload results"
3 files reviewed, no comments
CodSpeed Performance ReportMerging #5843 will not alter performanceComparing Summary
|
the following:
would be converted to