@@ -285,19 +285,19 @@ def CheckNoEffectYet():
285285 assert effect_triggers_after_final_render .current
286286
287287
288- async def test_use_effect_cleanup_occurs_on_will_render ():
288+ async def test_use_effect_cleanup_occurs_before_next_effect ():
289289 element_hook = HookCatcher ()
290290 cleanup_triggered = idom .Ref (False )
291- cleanup_triggered_before_next_render = idom .Ref (False )
291+ cleanup_triggered_before_next_effect = idom .Ref (False )
292292
293293 @idom .element
294294 @element_hook .capture
295295 def ElementWithEffect ():
296- if cleanup_triggered .current :
297- cleanup_triggered_before_next_render .current = True
298-
299296 @idom .hooks .use_effect
300297 def effect ():
298+ if cleanup_triggered .current :
299+ cleanup_triggered_before_next_effect .current = True
300+
301301 def cleanup ():
302302 cleanup_triggered .current = True
303303
@@ -314,7 +314,7 @@ def cleanup():
314314 await layout .render ()
315315
316316 assert cleanup_triggered .current
317- assert cleanup_triggered_before_next_render .current
317+ assert cleanup_triggered_before_next_effect .current
318318
319319
320320async def test_use_effect_cleanup_occurs_on_will_unmount ():
@@ -352,7 +352,7 @@ def cleanup():
352352 assert cleanup_triggered_before_next_render .current
353353
354354
355- async def test_use_effect_memoization ():
355+ async def test_memoized_effect_on_recreated_if_args_change ():
356356 element_hook = HookCatcher ()
357357 set_state_callback = idom .Ref (None )
358358 effect_run_count = idom .Ref (0 )
@@ -392,6 +392,44 @@ def effect():
392392 assert effect_run_count .current == 2
393393
394394
395+ async def test_memoized_effect_cleanup_only_triggered_before_new_effect ():
396+ element_hook = HookCatcher ()
397+ set_state_callback = idom .Ref (None )
398+ cleanup_trigger_count = idom .Ref (0 )
399+
400+ first_value = 1
401+ second_value = 2
402+
403+ @idom .element
404+ @element_hook .capture
405+ def ElementWithEffect ():
406+ state , set_state_callback .current = idom .hooks .use_state (first_value )
407+
408+ @idom .hooks .use_effect (args = [state ])
409+ def effect ():
410+ def cleanup ():
411+ cleanup_trigger_count .current += 1
412+
413+ return cleanup
414+
415+ return idom .html .div ()
416+
417+ async with idom .Layout (ElementWithEffect ()) as layout :
418+ await layout .render ()
419+
420+ assert cleanup_trigger_count .current == 0
421+
422+ element_hook .schedule_render ()
423+ await layout .render ()
424+
425+ assert cleanup_trigger_count .current == 0
426+
427+ set_state_callback .current (second_value )
428+ await layout .render ()
429+
430+ assert cleanup_trigger_count .current == 1
431+
432+
395433async def test_use_async_effect ():
396434 effect_ran = asyncio .Event ()
397435
@@ -481,7 +519,7 @@ def bad_effect():
481519 assert re .match ("Post-render effect .*? failed for .*?" , first_log_line )
482520
483521
484- async def test_error_in_effect_pre_render_cleanup_is_gracefully_handled (caplog ):
522+ async def test_error_in_effect_cleanup_is_gracefully_handled (caplog ):
485523 element_hook = HookCatcher ()
486524
487525 @idom .element
@@ -502,7 +540,7 @@ def bad_cleanup():
502540 await layout .render () # no error
503541
504542 first_log_line = next (iter (caplog .records )).msg .split ("\n " , 1 )[0 ]
505- assert re .match ("Pre -render effect .*? failed for .*?" , first_log_line )
543+ assert re .match ("Post -render effect .*? failed for .*?" , first_log_line )
506544
507545
508546async def test_error_in_effect_pre_unmount_cleanup_is_gracefully_handled (caplog ):
0 commit comments