exclude removed reactables

This commit is contained in:
Will McGugan
2023-02-09 11:04:37 +00:00
parent 6cd4d859b6
commit 6b91501ade
2 changed files with 19 additions and 5 deletions

View File

@@ -123,6 +123,11 @@ class MessagePump(metaclass=MessagePumpMeta):
""" """
return self.app._logger return self.app._logger
@property
def is_attached(self) -> bool:
"""Check the node is attached to the DOM"""
return self._parent is not None
def _attach(self, parent: MessagePump) -> None: def _attach(self, parent: MessagePump) -> None:
"""Set the parent, and therefore attach this node to the tree. """Set the parent, and therefore attach this node to the tree.

View File

@@ -242,9 +242,18 @@ class Reactive(Generic[ReactiveType]):
if callable(watch_function): if callable(watch_function):
invoke_watcher(watch_function, old_value, value) invoke_watcher(watch_function, old_value, value)
watchers: list[Callable] = getattr(obj, "__watchers", {}).get(name, []) # Process "global" watchers
for watcher in watchers: watchers: list[tuple[Reactable, Callable]]
invoke_watcher(watcher, old_value, value) watchers = getattr(obj, "__watchers", {}).get(name, [])
# Remove any watchers for reactables that have since closed
if watchers:
watchers[:] = [
(reactable, callback)
for reactable, callback in watchers
if reactable.is_attached and not reactable._closing
]
for _, callback in watchers:
invoke_watcher(callback, old_value, value)
@classmethod @classmethod
def _compute(cls, obj: Reactable) -> None: def _compute(cls, obj: Reactable) -> None:
@@ -333,11 +342,11 @@ def watch(
if not hasattr(obj, "__watchers"): if not hasattr(obj, "__watchers"):
setattr(obj, "__watchers", {}) setattr(obj, "__watchers", {})
watchers: dict[str, list[Callable]] = getattr(obj, "__watchers") watchers: dict[str, list[tuple[Reactable, Callable]]] = getattr(obj, "__watchers")
watcher_list = watchers.setdefault(attribute_name, []) watcher_list = watchers.setdefault(attribute_name, [])
if callback in watcher_list: if callback in watcher_list:
return return
watcher_list.append(callback) watcher_list.append((obj, callback))
if init: if init:
current_value = getattr(obj, attribute_name, None) current_value = getattr(obj, attribute_name, None)
Reactive._check_watchers(obj, attribute_name, current_value) Reactive._check_watchers(obj, attribute_name, current_value)