Repository navigation
fix: use_effect() skipping cleanups and re-running setups before cleanups finish - #7005
Open
ndonkoHenri wants to merge 4 commits into
Open
ndonkoHenri wants to merge 4 commits into
ndonkoHenri wants to merge 4 commits into
Conversation
…lled When a setup returned a cleanup and `cleanup=` was passed too, only one of them ran. The returned cleanup now runs first, then the argument, each reported on its own if it raises so the other still runs. A dependency change queued the cleanup and then the setup, and the setup cancelled the effect's tasks, killing the async cleanup it had just started. Only a still-running setup task is cancelled now. The effect tests move into test_use_effect.py, grouped into scheduling and end-to-end effect loop tests, and test_component_effects.py, left with an unmount test, becomes test_component_unmount.py.
An effect's cleanups now always finish, in order, before its setup runs again. Non-async cleanups run right away; once an async one starts, the rest finish in a task, and the effect's later setups and cleanups wait in a per-effect queue that runs as soon as the task is done. Superseded setups are skipped, and none runs after the component unmounts or the session closes or disconnects. Effect requests carry the setup function they were scheduled with, so each render's setup runs once. Cleanups run only if a setup ran since the last ones, a setup on an active effect runs its cleanups first, and a setup that runs after its component unmounted is cleaned up right away. Cleanup tasks are held by the session until they finish, so they aren't garbage collected while pending. A CancelledError raised by an effect counts as cancelled rather than failed, and one failing cleanup doesn't keep the others from running.
The use_effect docstring now explains when the setup and cleanups run, that cleanups always finish in order before the setup runs again, and that a returned cleanup sees its own setup's values while `cleanup` is the latest render's function. It gains an example that returns a cleanup. on_updated says it also runs after the component mounts, and the on_mounted, on_unmounted and on_updated docstrings drop the repeated types and note that `fn` may be async.
Deploying flet-website-v2 with
|
| Latest commit: |
71c4510
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://274698ab.flet-website-v2.pages.dev |
| Branch Preview URL: | https://fix-use-effect-cleanup-follo.flet-website-v2.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #6983, which fixed #6963: a cleanup returned by a
use_effectsetup was lost once the component re-rendered.What was still wrong
cleanup=as well as returning a cleanup ran only one of them.asynccleanups never ran on a dependency change. The cleanup started a task, then the setup that followed cancelled the effect's tasks, including the cleanup it had just started.asynccleanup could still be running when the setup ran again. For example, opening a new connection while the old one was still flushing and closing.What this does
An effect's cleanups now always finish, in order, before its setup runs again.
cleanup=. Non-asynccleanups run right away. Once anasyncone starts, the rest finish in a task.on_unmountedworking when a component unmounts before its effects ran.CancelledErrorraised by an effect counts as cancelled, not as an error.An
asyncsetup's return value still isn't used as a cleanup. Theuse_effectdocstring says so, and points tocleanup=instead.Docs
The
use_effectdocstring now explains the lifecycle, and that a returned cleanup sees its own setup's values whilecleanup=is the latest render's function. It also gains an example that returns a cleanup.on_updatednow says it also runs after mount, which it always did.Tests
The effect tests move into
tests/test_use_effect.py:TestEffectSchedulingchecks what a component queues, with_schedule_effectstubbed.TestEffectLoopdrives effects end-to-end through a realSessioneffect loop.The tests #6983 added in
test_component_effects.pyandtest_session_disconnect_buffering.pyare folded in or covered by the new ones.test_component_effects.py, left with a single unmount test, becomestest_component_unmount.py.Testing
test_use_effect.py(31 tests) passed over repeat runs with-W error. The fullfletsuite: 461 passed, 9 skipped.Task.cancelling()test is skipped, since it needs 3.11.flet-1.1.0.flet run --web. It ticked, re-rendered every second, and ran its returned cleanup exactly once per unmount, over two show/hide cycles.Summary by Sourcery
Make
use_effect()reliably complete each effect's cleanups before running replacement setups across synchronous, asynchronous, rerender, unmount, and session lifecycle transitions.Bug Fixes:
use_effect()cleanups run exactly once and in order, including both setup-returned andcleanup=callbacks, before a dependent setup runs again.Enhancements:
Documentation:
use_effect,on_mounted,on_unmounted, andon_updateddocumentation with lifecycle semantics, cleanup behavior, and a usage example.Tests:
Chores: