3030
3131
3232__all__  =  [
33-     "use_state " ,
33+     "use_callback " ,
3434    "use_effect" ,
35+     "use_memo" ,
3536    "use_reducer" ,
36-     "use_callback" ,
3737    "use_ref" ,
38-     "use_memo " ,
38+     "use_state " ,
3939]
4040
4141logger  =  getLogger (__name__ )
@@ -110,15 +110,15 @@ def use_effect(
110110
111111@overload  
112112def  use_effect (
113-     function : _EffectApplyFunc ,
113+     function : _SyncEffectFunc ,
114114    dependencies : Sequence [Any ] |  ellipsis  |  None  =  ...,
115115) ->  None : ...
116116
117117
118118def  use_effect (
119-     function : _EffectApplyFunc  |  None  =  None ,
119+     function : _SyncEffectFunc  |  None  =  None ,
120120    dependencies : Sequence [Any ] |  ellipsis  |  None  =  ...,
121- ) ->  Callable [[_EffectApplyFunc ], None ] |  None :
121+ ) ->  Callable [[_SyncEffectFunc ], None ] |  None :
122122    """See the full :ref:`Use Effect` docs for details 
123123
124124    Parameters: 
@@ -134,37 +134,87 @@ def use_effect(
134134        If not function is provided, a decorator. Otherwise ``None``. 
135135    """ 
136136    hook  =  current_hook ()
137- 
138137    dependencies  =  _try_to_infer_closure_values (function , dependencies )
139138    memoize  =  use_memo (dependencies = dependencies )
140139    last_clean_callback : Ref [_EffectCleanFunc  |  None ] =  use_ref (None )
141140
142-     def  add_effect (function : _EffectApplyFunc ) ->  None :
143-         if  not  asyncio .iscoroutinefunction (function ):
144-             sync_function  =  cast (_SyncEffectFunc , function )
145-         else :
146-             async_function  =  cast (_AsyncEffectFunc , function )
141+     def  add_effect (function : _SyncEffectFunc ) ->  None :
142+         async  def  effect (stop : asyncio .Event ) ->  None :
143+             if  last_clean_callback .current  is  not   None :
144+                 last_clean_callback .current ()
145+                 last_clean_callback .current  =  None 
146+             clean  =  last_clean_callback .current  =  function ()
147+             await  stop .wait ()
148+             if  clean  is  not   None :
149+                 clean ()
150+ 
151+         return  memoize (lambda : hook .add_effect (effect ))
152+ 
153+     if  function  is  not   None :
154+         add_effect (function )
155+         return  None 
156+ 
157+     return  add_effect 
158+ 
159+ 
160+ @overload  
161+ def  use_async_effect (
162+     function : None  =  None ,
163+     dependencies : Sequence [Any ] |  ellipsis  |  None  =  ...,
164+ ) ->  Callable [[_EffectApplyFunc ], None ]: ...
147165
148-             def  sync_function () ->  _EffectCleanFunc  |  None :
149-                 task  =  asyncio .create_task (async_function ())
150166
151-                 def  clean_future () ->  None :
152-                     if  not  task .cancel ():
153-                         try :
154-                             clean  =  task .result ()
155-                         except  asyncio .CancelledError :
156-                             pass 
157-                         else :
158-                             if  clean  is  not   None :
159-                                 clean ()
167+ @overload  
168+ def  use_async_effect (
169+     function : _AsyncEffectFunc ,
170+     dependencies : Sequence [Any ] |  ellipsis  |  None  =  ...,
171+ ) ->  None : ...
172+ 
173+ 
174+ def  use_async_effect (
175+     function : _AsyncEffectFunc  |  None  =  None ,
176+     dependencies : Sequence [Any ] |  ellipsis  |  None  =  ...,
177+ ) ->  Callable [[_AsyncEffectFunc ], None ] |  None :
178+     """See the full :ref:`Use Effect` docs for details 
179+ 
180+     Parameters: 
181+         function: 
182+             Applies the effect and can return a clean-up function 
183+         dependencies: 
184+             Dependencies for the effect. The effect will only trigger if the identity 
185+             of any value in the given sequence changes (i.e. their :func:`id` is 
186+             different). By default these are inferred based on local variables that are 
187+             referenced by the given function. 
188+ 
189+     Returns: 
190+         If not function is provided, a decorator. Otherwise ``None``. 
191+     """ 
192+     hook  =  current_hook ()
193+     dependencies  =  _try_to_infer_closure_values (function , dependencies )
194+     memoize  =  use_memo (dependencies = dependencies )
195+     last_clean_callback : Ref [_EffectCleanFunc  |  None ] =  use_ref (None )
196+ 
197+     def  add_effect (function : _AsyncEffectFunc ) ->  None :
198+         def  sync_executor () ->  _EffectCleanFunc  |  None :
199+             task  =  asyncio .create_task (function ())
160200
161-                 return  clean_future 
201+             def  clean_future () ->  None :
202+                 if  not  task .cancel ():
203+                     try :
204+                         clean  =  task .result ()
205+                     except  asyncio .CancelledError :
206+                         pass 
207+                     else :
208+                         if  clean  is  not   None :
209+                             clean ()
210+ 
211+             return  clean_future 
162212
163213        async  def  effect (stop : asyncio .Event ) ->  None :
164214            if  last_clean_callback .current  is  not   None :
165215                last_clean_callback .current ()
166216                last_clean_callback .current  =  None 
167-             clean  =  last_clean_callback .current  =  sync_function ()
217+             clean  =  last_clean_callback .current  =  sync_executor ()
168218            await  stop .wait ()
169219            if  clean  is  not   None :
170220                clean ()
@@ -174,8 +224,8 @@ async def effect(stop: asyncio.Event) -> None:
174224    if  function  is  not   None :
175225        add_effect (function )
176226        return  None 
177-      else : 
178-          return  add_effect 
227+ 
228+     return  add_effect 
179229
180230
181231def  use_debug_value (
0 commit comments