1919
2020from typing_extensions import TypeAlias
2121
22- from reactpy .config import REACTPY_DEBUG_MODE
23- from reactpy .core ._life_cycle_hook import (
24- Context ,
25- ContextProvider ,
26- EffectInfo ,
27- current_hook ,
28- )
29- from reactpy .core .types import Key , State
22+ from reactpy .config import REACTPY_DEBUG_MODE , REACTPY_EFFECT_DEFAULT_STOP_TIMEOUT
23+ from reactpy .core ._life_cycle_hook import EffectInfo , current_hook
24+ from reactpy .core .types import Context , Key , State , VdomDict
3025from reactpy .utils import Ref
3126
3227if not TYPE_CHECKING :
@@ -109,6 +104,7 @@ def dispatch(new: _Type | Callable[[_Type], _Type]) -> None:
109104def use_effect (
110105 function : None = None ,
111106 dependencies : Sequence [Any ] | ellipsis | None = ...,
107+ stop_timeout : float = ...,
112108) -> Callable [[_EffectFunc ], None ]:
113109 ...
114110
@@ -117,13 +113,15 @@ def use_effect(
117113def use_effect (
118114 function : _EffectFunc ,
119115 dependencies : Sequence [Any ] | ellipsis | None = ...,
116+ stop_timeout : float = ...,
120117) -> None :
121118 ...
122119
123120
124121def use_effect (
125122 function : _EffectFunc | None = None ,
126123 dependencies : Sequence [Any ] | ellipsis | None = ...,
124+ stop_timeout : float = REACTPY_EFFECT_DEFAULT_STOP_TIMEOUT .current ,
127125) -> Callable [[_EffectFunc ], None ] | None :
128126 """See the full :ref:`Use Effect` docs for details
129127
@@ -135,6 +133,11 @@ def use_effect(
135133 of any value in the given sequence changes (i.e. their :func:`id` is
136134 different). By default these are inferred based on local variables that are
137135 referenced by the given function.
136+ stop_timeout:
137+ The maximum amount of time to wait for the effect to cleanup after it has
138+ been signaled to stop. If the timeout is reached, an exception will be
139+ logged and the effect will be cancelled. This does not apply to synchronous
140+ effects.
138141
139142 Returns:
140143 If not function is provided, a decorator. Otherwise ``None``.
@@ -150,8 +153,7 @@ def add_effect(function: _EffectFunc) -> None:
150153 async def create_effect_task () -> EffectInfo :
151154 if effect_info .current is not None :
152155 last_effect_info = effect_info .current
153- last_effect_info .stop .set ()
154- await last_effect_info .task
156+ await last_effect_info .signal_stop (stop_timeout )
155157
156158 stop = asyncio .Event ()
157159 info = EffectInfo (asyncio .create_task (effect (stop )), stop )
@@ -173,7 +175,8 @@ def _cast_async_effect(function: Callable[..., Any]) -> _AsyncEffectFunc:
173175 return function
174176
175177 warnings .warn (
176- 'Async effect functions should accept a "stop" asyncio.Event as their first argument' ,
178+ 'Async effect functions should accept a "stop" asyncio.Event as their '
179+ "first argument. This will be required in a future version of ReactPy." ,
177180 stacklevel = 3 ,
178181 )
179182
@@ -249,8 +252,8 @@ def context(
249252 * children : Any ,
250253 value : _Type = default_value ,
251254 key : Key | None = None ,
252- ) -> ContextProvider [_Type ]:
253- return ContextProvider (
255+ ) -> _ContextProvider [_Type ]:
256+ return _ContextProvider (
254257 * children ,
255258 value = value ,
256259 key = key ,
@@ -280,7 +283,28 @@ def use_context(context: Context[_Type]) -> _Type:
280283 raise TypeError (f"{ context } has no 'value' kwarg" ) # nocov
281284 return cast (_Type , context .__kwdefaults__ ["value" ])
282285
283- return provider ._value
286+ return provider .value
287+
288+
289+ class _ContextProvider (Generic [_Type ]):
290+ def __init__ (
291+ self ,
292+ * children : Any ,
293+ value : _Type ,
294+ key : Key | None ,
295+ type : Context [_Type ],
296+ ) -> None :
297+ self .children = children
298+ self .key = key
299+ self .type = type
300+ self .value = value
301+
302+ def render (self ) -> VdomDict :
303+ current_hook ().set_context_provider (self )
304+ return {"tagName" : "" , "children" : self .children }
305+
306+ def __repr__ (self ) -> str :
307+ return f"ContextProvider({ self .type } )"
284308
285309
286310_ActionType = TypeVar ("_ActionType" )
0 commit comments