22
33import logging
44from asyncio import gather
5- from collections .abc import AsyncGenerator
5+ from collections .abc import Awaitable
66from typing import Any , Callable , TypeVar
77
88from anyio import Semaphore
@@ -41,7 +41,7 @@ class LifeCycleHook:
4141 .. testcode::
4242
4343 from reactpy.core._life_cycle_hook import LifeCycleHook
44- from reactpy.core.hooks import current_hook, COMPONENT_DID_RENDER_EFFECT
44+ from reactpy.core.hooks import current_hook
4545
4646 # this function will come from a layout implementation
4747 schedule_render = lambda: ...
@@ -63,7 +63,11 @@ class LifeCycleHook:
6363
6464 # and save state or add effects
6565 current_hook().use_state(lambda: ...)
66- current_hook().add_effect(COMPONENT_DID_RENDER_EFFECT, lambda: ...)
66+
67+ async def effect():
68+ yield
69+
70+ current_hook().add_effect(effect)
6771 finally:
6872 await hook.affect_component_did_render()
6973
@@ -88,10 +92,10 @@ class LifeCycleHook:
8892 "__weakref__" ,
8993 "_context_providers" ,
9094 "_current_state_index" ,
91- "_pending_effects" ,
95+ "_effect_cleanups" ,
96+ "_effect_startups" ,
9297 "_render_access" ,
9398 "_rendered_atleast_once" ,
94- "_running_effects" ,
9599 "_schedule_render_callback" ,
96100 "_schedule_render_later" ,
97101 "_state" ,
@@ -110,8 +114,8 @@ def __init__(
110114 self ._rendered_atleast_once = False
111115 self ._current_state_index = 0
112116 self ._state : tuple [Any , ...] = ()
113- self ._pending_effects : list [AsyncGenerator [ None , None ]] = []
114- self ._running_effects : list [AsyncGenerator [ None , None ]] = []
117+ self ._effect_startups : list [Callable [[], Awaitable [ None ] ]] = []
118+ self ._effect_cleanups : list [Callable [[], Awaitable [ None ] ]] = []
115119 self ._render_access = Semaphore (1 ) # ensure only one render at a time
116120
117121 def schedule_render (self ) -> None :
@@ -131,9 +135,14 @@ def use_state(self, function: Callable[[], T]) -> T:
131135 self ._current_state_index += 1
132136 return result
133137
134- def add_effect (self , effect_func : Callable [[], AsyncGenerator [None , None ]]) -> None :
138+ def add_effect (
139+ self ,
140+ start_effect : Callable [[], Awaitable [None ]],
141+ clean_effect : Callable [[], Awaitable [None ]],
142+ ) -> None :
135143 """Add an effect to this hook"""
136- self ._pending_effects .append (effect_func ())
144+ self ._effect_startups .append (start_effect )
145+ self ._effect_cleanups .append (clean_effect )
137146
138147 def set_context_provider (self , provider : ContextProviderType [Any ]) -> None :
139148 self ._context_providers [provider .type ] = provider
@@ -155,29 +164,28 @@ async def affect_component_did_render(self) -> None:
155164 self ._rendered_atleast_once = True
156165 self ._current_state_index = 0
157166 self ._render_access .release ()
167+ del self .component
158168
159169 async def affect_layout_did_render (self ) -> None :
160170 """The layout completed a render"""
161171 try :
162- await gather (* [g .asend (None ) for g in self ._pending_effects ])
163- self ._running_effects .extend (self ._pending_effects )
172+ await gather (* [start () for start in self ._effect_startups ])
164173 except Exception :
165174 logger .exception ("Error during effect startup" )
166175 finally :
167- self ._pending_effects .clear ()
168- if self ._schedule_render_later :
169- self ._schedule_render ()
170- self ._schedule_render_later = False
171- del self .component
176+ self ._effect_startups .clear ()
177+ if self ._schedule_render_later :
178+ self ._schedule_render ()
179+ self ._schedule_render_later = False
172180
173181 async def affect_component_will_unmount (self ) -> None :
174182 """The component is about to be removed from the layout"""
175183 try :
176- await gather (* [g . aclose () for g in self ._running_effects ])
184+ await gather (* [clean () for clean in self ._effect_cleanups ])
177185 except Exception :
178186 logger .exception ("Error during effect cleanup" )
179187 finally :
180- self ._running_effects .clear ()
188+ self ._effect_cleanups .clear ()
181189
182190 def set_current (self ) -> None :
183191 """Set this hook as the active hook in this thread
0 commit comments