Skip to content

Commit 491c05a

Browse files
authored
Fix unmount (#901)
* remove upper bound * revert #886 + add test + misc * changelog entry * changes for latest black
1 parent cc723de commit 491c05a

File tree

14 files changed

+56
-41
lines changed

14 files changed

+56
-41
lines changed

docs/source/_exts/idom_example.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919

2020
class WidgetExample(SphinxDirective):
21-
2221
has_content = False
2322
required_arguments = 1
2423
_next_id = 0

docs/source/_exts/idom_view.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414

1515
class IteractiveWidget(SphinxDirective):
16-
1716
has_content = False
1817
required_arguments = 1
1918
_next_id = 0

docs/source/about/changelog.rst

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@ more info, see the :ref:`Contributor Guide <Creating a Changelog Entry>`.
2323
Unreleased
2424
----------
2525

26-
No changes.
26+
**Reverted**
27+
28+
- :pull:`901` - reverts :pull:`886` due to :issue:`896`
29+
30+
**Fixed**
31+
32+
- :issue:`896` - Stale event handlers after disconnect/reconnect cycle
2733

2834

2935
v1.0.0-a1

requirements/pkg-deps.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ requests >=2
77
colorlog >=6
88
asgiref >=3
99
lxml >=4
10-
click >=8, <9
10+
click >=8

src/client/packages/idom-client-react/src/mount.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ function mountLayoutWithReconnectingWebSocket(
3838
socket.onopen = (event) => {
3939
console.info(`IDOM WebSocket connected.`);
4040

41+
if (mountState.everMounted) {
42+
ReactDOM.unmountComponentAtNode(element);
43+
}
4144
_resetOpenMountState(mountState);
4245

4346
mountLayout(element, {

src/idom/backend/tornado.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ def _setup_single_view_dispatcher_route(
158158

159159

160160
class IndexHandler(RequestHandler):
161-
162161
_index_html: str
163162

164163
def initialize(self, index_html: str) -> None:

src/idom/core/hooks.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ def use_state(initial_value: _Type | Callable[[], _Type]) -> State[_Type]:
7575

7676

7777
class _CurrentState(Generic[_Type]):
78-
7978
__slots__ = "value", "dispatch"
8079

8180
def __init__(
@@ -148,11 +147,9 @@ def use_effect(
148147
last_clean_callback: Ref[Optional[_EffectCleanFunc]] = use_ref(None)
149148

150149
def add_effect(function: _EffectApplyFunc) -> None:
151-
152150
if not asyncio.iscoroutinefunction(function):
153151
sync_function = cast(_SyncEffectFunc, function)
154152
else:
155-
156153
async_function = cast(_AsyncEffectFunc, function)
157154

158155
def sync_function() -> Optional[_EffectCleanFunc]:

src/idom/core/layout.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,6 @@ class _LifeCycleState(NamedTuple):
651651

652652

653653
class _ThreadSafeQueue(Generic[_Type]):
654-
655654
__slots__ = "_loop", "_queue", "_pending"
656655

657656
def __init__(self) -> None:

src/idom/core/vdom.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,6 @@ def separate_attributes_and_event_handlers(
258258
separated_handlers: DefaultDict[str, list[EventHandlerType]] = DefaultDict(list)
259259

260260
for k, v in attributes.items():
261-
262261
handler: EventHandlerType
263262

264263
if callable(v):

src/idom/testing/common.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ async def until(
5656
condition: Callable[[_R], bool],
5757
timeout: float = IDOM_TESTING_DEFAULT_TIMEOUT.current,
5858
delay: float = _DEFAULT_POLL_DELAY,
59+
description: str = "condition to be true",
5960
) -> None:
6061
"""Check that the coroutines result meets a condition within the timeout"""
6162
started_at = time.time()
@@ -66,7 +67,7 @@ async def until(
6667
break
6768
elif (time.time() - started_at) > timeout: # pragma: no cover
6869
raise TimeoutError(
69-
f"Condition not met within {timeout} "
70+
f"Expected {description} after {timeout} "
7071
f"seconds - last value was {result!r}"
7172
)
7273

@@ -77,7 +78,12 @@ async def until_is(
7778
delay: float = _DEFAULT_POLL_DELAY,
7879
) -> None:
7980
"""Wait until the result is identical to the given value"""
80-
return await self.until(lambda left: left is right, timeout, delay)
81+
return await self.until(
82+
lambda left: left is right,
83+
timeout,
84+
delay,
85+
f"value to be identical to {right!r}",
86+
)
8187

8288
async def until_equals(
8389
self,
@@ -86,7 +92,12 @@ async def until_equals(
8692
delay: float = _DEFAULT_POLL_DELAY,
8793
) -> None:
8894
"""Wait until the result is equal to the given value"""
89-
return await self.until(lambda left: left == right, timeout, delay)
95+
return await self.until(
96+
lambda left: left == right,
97+
timeout,
98+
delay,
99+
f"value to equal {right!r}",
100+
)
90101

91102

92103
class HookCatcher:

0 commit comments

Comments
 (0)