
Using Efficient Effects
Use this skill to choose the cheapest correct effect API in Jetpack Compose, ...
Install
npx skills add skydoves/compose-performance-skills --skill using-efficient-effects -g -a claude-code -y- Repository
- skydoves/compose-performance-skills524
- Category
- Engineering
- Updated
- 5mo ago
- License
- Apache-2.0
- Context cost
- Mediumabout 2,993 tokens
- Runs scripts
- No, instructions only
What it does
Use this skill to choose the cheapest correct effect API in Jetpack Compose, `LaunchedEffect`, `DisposableEffect`, `SideEffect`, `rememberUpdatedState`, and skydoves/compose-effects' `RememberedEffect` and `ViewModelStoreScope`. Covers stale-callback bugs in long-lived `LaunchedEffect`, setup/teardown for non-coroutine subscribers, avoiding a coroutine scope just to react to a key change, and per-row ViewModels in a `LazyColumn`. Trigger when the user mentions LaunchedEffect, DisposableEffect, RememberedEffect, SideEffect, rememberUpdatedState, ViewModelStoreScope, effect restarts unexpectedly, leaked listener, or per-item ViewModel.
Using Efficient Effects, pick the cheapest correct effect API
Compose ships three effect APIs by default: LaunchedEffect (coroutine, restarts on key change), DisposableEffect (setup/teardown with a cleanup block), and SideEffect (runs on every successful composition). The skydoves/compose-effects library adds RememberedEffect, a non-coroutine analog of LaunchedEffect. Picking the wrong API wastes a coroutine scope, leaks a listener, or silently drops the latest version of a callback. This skill is the decision tree.
When to use this skill
- The user asks which effect API to choose, or why a
LaunchedEffectrestarts unexpectedly. - A long-lived
LaunchedEffectcalls a stale version of a callback that the parent has updated. - A non-Compose subscriber (listener, observer, broadcast receiver, GL surface) needs setup at composition entry and teardown on key change or exit.
- A composable just needs to react to a key change synchronously and a coroutine scope is overkill.
- A
LazyColumnrow needs its ownViewModelinstance (e.g. one VM per chat row, one VM per feed card) and the parent VM store would leak state across rows. - The user is debugging unexpected effect restarts, leaked listeners, or per-frame allocations from
SideEffect.
When NOT to use this skill
- Pure derivation of one
State<T>from another, usederivedStateOf. See../../recomposition/choosing-derivedstateof/SKILL.md. - Collecting a flow that originates outside the composition, use
collectAsStateWithLifecycle. See../collecting-flows-safely/SKILL.md. - One-shot computation that must survive recomposition without re-running, use
remember { ... }, notLaunchedEffect(Unit).
