fix(event): handle mixed rx.cond event/function returns in event lambdas#6354
fix(event): handle mixed rx.cond event/function returns in event lambdas#6354BABTUNA wants to merge 1 commit intoreflex-dev:mainfrom
Conversation
Greptile SummaryThis PR fixes Confidence Score: 5/5Safe to merge — the fix is correct and all remaining findings are P2 style/quality suggestions that do not block the primary use case. No P0 or P1 findings. The over-broad type guard and missing event_actions propagation are both P2: the former is harmless in practice, and the latter is consistent with pre-existing FunctionVar behavior rather than a regression. packages/reflex-base/src/reflex_base/event/init.py — the new type guard condition and hard-coded event_actions warrant a second look, but neither blocks merge. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["call_event_fn(fn, arg_spec)"] --> B["Invoke fn with parsed args"]
B --> C["Normalize to list: out = [...]"]
C --> D["For each e in out"]
D --> E{"isinstance(e, EventHandler)?"}
E -- Yes --> F["call_event_handler(e, ...)"]
E -- No --> G{"isinstance(e, EventChain)?"}
F --> G
G -- Yes --> H["e = Var.create(e)"]
G -- No --> I{"isinstance(e, Var) and\nnot EventVar/FunctionVar and\ntypehint_issubclass(type, EventSpec|Callable)?"}
H --> I
I -- Yes --> J["_dispatch_mixed_event_var(e)\n→ JS arrow fn with typeof branch"]
I -- No --> K{"isinstance(e, EventSpec|FunctionVar|EventVar)?"}
J --> K
K -- No --> L["Raise EventHandlerValueError"]
K -- Yes --> M["events.append(e)"]
M --> D
J --> N["JS: (...args) => {\n const __event_or_fn = ...;\n if (typeof __event_or_fn === 'function')\n return __event_or_fn(...args);\n return addEvents([__event_or_fn], args, {});\n}"]
Reviews (1): Last reviewed commit: "Handle mixed rx.cond event/function retu..." | Re-trigger Greptile |
| if ( | ||
| isinstance(e, Var) | ||
| and not isinstance(e, (EventVar, FunctionVar)) | ||
| and typehint_issubclass(e._var_type, EventSpec | Callable) | ||
| ): | ||
| e = _dispatch_mixed_event_var(e) |
There was a problem hiding this comment.
Over-broad type guard can match non-union types
The condition typehint_issubclass(e._var_type, EventSpec | Callable) returns True for any Var whose _var_type is a subclass of either EventSpec or Callable alone — not just for union types containing both. A plain Var[EventSpec] or Var[Callable] would both be caught here and wrapped unnecessarily by _dispatch_mixed_event_var. While harmless in practice, it silently widens the handling surface beyond the stated intent of "mixed" conditional types. Consider adding a union-origin guard:
if (
isinstance(e, Var)
and not isinstance(e, (EventVar, FunctionVar))
and get_origin(e._var_type) in (Union, types.UnionType)
and typehint_issubclass(e._var_type, EventSpec | Callable)
):
e = _dispatch_mixed_event_var(e)| f'if (typeof {event_like_name} === "function") {{' | ||
| f"return {event_like_name}(...args);" | ||
| "}" | ||
| f"return {CompileVars.ADD_EVENTS}([{event_like_name}], args, ({{ }}));" |
There was a problem hiding this comment.
Chain-level
event_actions not propagated to conditional backend events
_dispatch_mixed_event_var hard-codes ({ }) (an empty object) as the event_actions argument to addEvents. If this dispatcher ends up in an EventChain carrying chain-level event_actions (e.g. preventDefault: True), those actions will be silently dropped for any conditional branch that resolves to a backend event. The existing EventVar→invocation.call(...) path threads those actions correctly, but the new FunctionVar wrapper bypasses that path. This is consistent with pre-existing FunctionVar behavior (not a regression), but worth noting for future callers.
| f'if (typeof {event_like_name} === "function") {{' | ||
| f"return {event_like_name}(...args);" | ||
| "}" | ||
| f"return {CompileVars.ADD_EVENTS}([{event_like_name}], args, ({{ }}));" |
There was a problem hiding this comment.
Extraneous spaces in empty object literal
({{ }}) produces ({ }) — a parenthesised empty object with two interior spaces — in the emitted JavaScript. This is valid but inconsistent with idiomatic {}. Consider {{}} instead.
| f"return {CompileVars.ADD_EVENTS}([{event_like_name}], args, ({{ }}));" | |
| f"return {CompileVars.ADD_EVENTS}([{event_like_name}], args, ({{}}));" |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
All Submissions:
github.com/reflex-dev/reflex/blob/main/CONTRIBUTING.md) file?
Requests for the desired
changed?
Type of change
New Feature Submission:
Changes To Core Features:
like us to include them?
Description
This fixes event-lambda handling for
rx.cond(...)expressions that returnmixed event-like values (frontend function branch vs backend event branch).
Before this change,
call_event_fnrejected this pattern because thelambda return was a
Var(CustomVarOperation) rather than one of:EventSpecEventHandlerEventVarFunctionVarThat made valid mixed conditional handlers fail during event-chain
creation.