diff --git a/integration/test_event_actions.py b/integration/test_event_actions.py
index d446b6663..8f5e0788b 100644
--- a/integration/test_event_actions.py
+++ b/integration/test_event_actions.py
@@ -1,5 +1,6 @@
"""Ensure stopPropagation and preventDefault work as expected."""
+import asyncio
from typing import Callable, Coroutine, Generator
import pytest
@@ -21,13 +22,31 @@ def TestEventAction():
def on_click2(self):
self.order.append("on_click2")
- @rx.var
- def token(self) -> str:
- return self.get_token()
+ class EventFiringComponent(rx.Component):
+ """A component that fires onClick event without passing DOM event."""
+
+ tag = "EventFiringComponent"
+
+ def _get_custom_code(self) -> str | None:
+ return """
+ function EventFiringComponent(props) {
+ return (
+
props.onClick("foo")}>
+ Event Firing Component
+
+ )
+ }"""
+
+ def get_event_triggers(self):
+ return {"on_click": lambda: []}
def index():
return rx.vstack(
- rx.input(value=EventActionState.token, is_read_only=True, id="token"),
+ rx.input(
+ value=EventActionState.router.session.client_token,
+ is_read_only=True,
+ id="token",
+ ),
rx.button("No events", id="btn-no-events"),
rx.button(
"Stop Prop Only",
@@ -90,6 +109,18 @@ def TestEventAction():
).stop_propagation.prevent_default,
id="link-stop-propagation-prevent-default",
),
+ EventFiringComponent.create(
+ id="custom-stop-propagation",
+ on_click=EventActionState.on_click( # type: ignore
+ "custom-stop-propagation"
+ ).stop_propagation,
+ ),
+ EventFiringComponent.create(
+ id="custom-prevent-default",
+ on_click=EventActionState.on_click( # type: ignore
+ "custom-prevent-default"
+ ).prevent_default,
+ ),
rx.list(
rx.foreach(
EventActionState.order, # type: ignore
@@ -202,6 +233,14 @@ def poll_for_order(
("link-prevent-default", ["on_click:link_prevent_default", "on_click:outer"]),
("link-prevent-default-only", ["on_click:outer"]),
("link-stop-propagation-prevent-default", ["on_click:link_both"]),
+ (
+ "custom-stop-propagation",
+ ["on_click:custom-stop-propagation", "on_click:outer"],
+ ),
+ (
+ "custom-prevent-default",
+ ["on_click:custom-prevent-default", "on_click:outer"],
+ ),
],
)
@pytest.mark.usefixtures("token")
@@ -226,6 +265,9 @@ async def test_event_actions(
prev_url = driver.current_url
el.click()
+ if "on_click:outer" not in exp_order:
+ # really make sure the outer event is not fired
+ await asyncio.sleep(0.5)
await poll_for_order(exp_order)
if element_id.startswith("link") and "prevent-default" not in element_id:
diff --git a/reflex/.templates/web/utils/state.js b/reflex/.templates/web/utils/state.js
index fb0208a86..673e317d3 100644
--- a/reflex/.templates/web/utils/state.js
+++ b/reflex/.templates/web/utils/state.js
@@ -488,10 +488,10 @@ export const useEventLoop = (
// Function to add new events to the event queue.
const addEvents = (events, _e, event_actions) => {
- if (event_actions?.preventDefault && _e) {
+ if (event_actions?.preventDefault && _e?.preventDefault) {
_e.preventDefault();
}
- if (event_actions?.stopPropagation && _e) {
+ if (event_actions?.stopPropagation && _e?.stopPropagation) {
_e.stopPropagation();
}
queueEvents(events, socket)