change logic to check if event handlers actually contain state. Also delay websocket object check in state.js so server side events can get executed for stateless apps
This commit is contained in:
parent
7d2a5c238a
commit
6437067de8
@ -213,6 +213,10 @@ export const applyEvent = async (event, socket) => {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only proceed if the socket is up, otherwise we throw the event into the void
|
||||||
|
if (!socket) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// Update token and router data (if missing).
|
// Update token and router data (if missing).
|
||||||
event.token = getToken();
|
event.token = getToken();
|
||||||
if (
|
if (
|
||||||
@ -246,6 +250,10 @@ export const applyEvent = async (event, socket) => {
|
|||||||
* @returns Whether the event was sent.
|
* @returns Whether the event was sent.
|
||||||
*/
|
*/
|
||||||
export const applyRestEvent = async (event, socket) => {
|
export const applyRestEvent = async (event, socket) => {
|
||||||
|
// Only proceed if the socket is up, otherwise we throw the event into the void
|
||||||
|
if (!socket) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
let eventSent = false;
|
let eventSent = false;
|
||||||
if (event.handler === "uploadFiles") {
|
if (event.handler === "uploadFiles") {
|
||||||
|
|
||||||
@ -282,11 +290,6 @@ export const queueEvents = async (events, socket) => {
|
|||||||
* @param socket The socket object to send the event on.
|
* @param socket The socket object to send the event on.
|
||||||
*/
|
*/
|
||||||
export const processEvent = async (socket) => {
|
export const processEvent = async (socket) => {
|
||||||
// Only proceed if the socket is up, otherwise we throw the event into the void
|
|
||||||
if (!socket) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only proceed if we're not already processing an event.
|
// Only proceed if we're not already processing an event.
|
||||||
if (event_queue.length === 0 || event_processing) {
|
if (event_queue.length === 0 || event_processing) {
|
||||||
return;
|
return;
|
||||||
|
@ -541,9 +541,7 @@ class App(LifespanMixin, Base):
|
|||||||
|
|
||||||
# Ensure state is enabled if this page uses state.
|
# Ensure state is enabled if this page uses state.
|
||||||
if self.state is None:
|
if self.state is None:
|
||||||
if on_load or component._has_event_triggers(
|
if on_load or component._has_stateful_event_triggers():
|
||||||
exclude_event_trigger_values=[constants.ColorMode.TOGGLE]
|
|
||||||
):
|
|
||||||
self._enable_state()
|
self._enable_state()
|
||||||
else:
|
else:
|
||||||
for var in component._get_vars(include_children=True):
|
for var in component._get_vars(include_children=True):
|
||||||
|
@ -7,7 +7,7 @@ import typing
|
|||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from functools import lru_cache, wraps
|
from functools import lru_cache, wraps
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace, LambdaType
|
||||||
from typing import (
|
from typing import (
|
||||||
Any,
|
Any,
|
||||||
Callable,
|
Callable,
|
||||||
@ -1113,65 +1113,38 @@ class Component(BaseComponent, ABC):
|
|||||||
|
|
||||||
return vars
|
return vars
|
||||||
|
|
||||||
def _event_triggers_contains_excluded_values(
|
|
||||||
self, exclude_event_trigger_values: list[str]
|
|
||||||
) -> bool:
|
|
||||||
"""Check if the component's event triggers contain excluded value names.
|
|
||||||
When an event trigger value is a Var, we check the var name else, if the value is
|
|
||||||
an EventChain, we go through all the events comparing the function names (or qualname for non-state
|
|
||||||
event handlers).
|
|
||||||
|
|
||||||
Args:
|
def _event_trigger_values_use_state(self) -> bool:
|
||||||
exclude_event_trigger_values: excluded values to check for.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
If the component's event triggers contain any excluded value
|
|
||||||
|
|
||||||
"""
|
|
||||||
for trigger in self.event_triggers.values():
|
for trigger in self.event_triggers.values():
|
||||||
if isinstance(trigger, EventChain):
|
if isinstance(trigger, EventChain):
|
||||||
for event in trigger.events:
|
for event in trigger.events:
|
||||||
if (
|
if event.handler.state_full_name or isinstance(event.handler.fn, LambdaType) and event.handler.fn.__name__== (lambda: None).__name__:
|
||||||
(
|
|
||||||
event.handler.state_full_name
|
|
||||||
and event.handler.fn.__name__
|
|
||||||
in exclude_event_trigger_values
|
|
||||||
)
|
|
||||||
or not event.handler.state_full_name
|
|
||||||
and event.handler.fn.__qualname__
|
|
||||||
in exclude_event_trigger_values
|
|
||||||
):
|
|
||||||
return True
|
return True
|
||||||
elif (
|
elif isinstance(trigger, Var) and trigger._var_state:
|
||||||
isinstance(trigger, Var)
|
|
||||||
and trigger._var_name in exclude_event_trigger_values
|
|
||||||
):
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _has_event_triggers(
|
def _has_stateful_event_triggers(self):
|
||||||
self, exclude_event_trigger_values: list[str] | None = None
|
|
||||||
) -> bool:
|
|
||||||
"""Check if the component or children have any event triggers.
|
|
||||||
|
|
||||||
Args:
|
if self.event_triggers and self._event_trigger_values_use_state():
|
||||||
exclude_event_trigger_values: Event trigger var names to exclude from this check.
|
return True
|
||||||
|
else:
|
||||||
|
for child in self.children:
|
||||||
|
if isinstance(child, Component) and child._has_stateful_event_triggers():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _has_event_triggers(self) -> bool:
|
||||||
|
"""Check if the component or children have any event triggers.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
True if the component or children have any event triggers.
|
True if the component or children have any event triggers.
|
||||||
"""
|
"""
|
||||||
if exclude_event_trigger_values is None:
|
if self.event_triggers:
|
||||||
exclude_event_trigger_values = []
|
|
||||||
|
|
||||||
if self.event_triggers and not self._event_triggers_contains_excluded_values(
|
|
||||||
exclude_event_trigger_values
|
|
||||||
):
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
for child in self.children:
|
for child in self.children:
|
||||||
if isinstance(child, Component) and child._has_event_triggers(
|
if isinstance(child, Component) and child._has_event_triggers():
|
||||||
exclude_event_trigger_values
|
|
||||||
):
|
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -2146,6 +2146,17 @@ class TriggerState(rx.State):
|
|||||||
["_console", "_alert"],
|
["_console", "_alert"],
|
||||||
False,
|
False,
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
rx.box(
|
||||||
|
rx.text(
|
||||||
|
"random text",
|
||||||
|
on_click=lambda x: x,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
["_console", "_alert"],
|
||||||
|
False,
|
||||||
|
),
|
||||||
|
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_has_event_triggers(component, exclude_event_trigger_values, output):
|
def test_has_event_triggers(component, exclude_event_trigger_values, output):
|
||||||
|
Loading…
Reference in New Issue
Block a user