using-efficient-effects

Selects the correct Jetpack Compose effect API for coroutines, listeners, and per-row ViewModels.

Updated May 31, 2026
One-click install
npx skills add https://github.com/decoutkhanqindev/Lich-Viet-Loc-Phat --skill using-efficient-effects-decoutkhanqindev
Or copy as Structured Prompt for Agent▼
Please help me install this Agent Skill.
Skill: using-efficient-effects
Source: https://github.com/decoutkhanqindev/Lich-Viet-Loc-Phat/tree/main/.claude/skills/using-efficient-effects
Command: npx skills add https://github.com/decoutkhanqindev/Lich-Viet-Loc-Phat --skill using-efficient-effects-decoutkhanqindev

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? Choosing the wrong Compose effect API wastes coroutine scopes, leaks listeners, or silently drops updated callbacks. This Skill provides a decision tree for picking between LaunchedEffect, DisposableEffect, SideEffect, rememberUpdatedState, and skydoves/compose-effects' RememberedEffect and ViewModelStoreScope. ## Core Features & Use Cases - Effect API decision tree: Maps each scenario (coroutine work, setup/teardown, synchronous key reaction, per-commit publishing) to the cheapest correct API. - Stale callback fixes: Shows how rememberUpdatedState keeps long-lived LaunchedEffect blocks reading the latest callback without restarting. - Per-row ViewModels: Uses ViewModelStoreScope with a stable key so each LazyColumn row gets its own ViewModel instead of sharing the parent store. - Use Case: A chat screen where each row needs its own ViewModel and a timer callback keeps firing a stale lambda — apply ViewModelStoreScope(key = row.id) and rememberUpdatedState to fix both. ## Quick Start Ask the assistant to review your composable and recommend the correct effect API for a listener that leaks or a LaunchedEffect that restarts unexpectedly.

Frequently Asked Questions about using-efficient-effects

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I fix a stale callback inside LaunchedEffect?▼

Wrap the callback with rememberUpdatedState and read the latest reference inside the effect. The coroutine keeps running without restarting while always invoking the most recent lambda passed by the parent.

LaunchedEffect vs DisposableEffect: which should I use?▼

Use LaunchedEffect when the work suspends or needs a coroutine, such as network calls or animations. Use DisposableEffect for non-coroutine subscribers like listeners or observers, since its onDispose block guarantees cleanup on key change and composition exit.

How do I give each LazyColumn row its own ViewModel?▼

Wrap the row content in ViewModelStoreScope(key = row.id) from com.github.skydoves:compose-effects-viewmodel, then call hiltViewModel() inside. Without it, every row resolves against the parent store and shares one ViewModel instance.

Does RememberedEffect replace LaunchedEffect?▼

RememberedEffect from skydoves/compose-effects replaces LaunchedEffect only when the body does not suspend. It reacts to key changes synchronously without allocating a coroutine scope, but it has no onDispose, so pair it with DisposableEffect if teardown is needed.

Why does my LaunchedEffect restart unexpectedly?▼

The effect restarts whenever any key in its key set changes value. Lying about the key set or capturing values not listed as keys causes missed updates or surprise restarts; key the effect on every value it closes over that should trigger a restart.

When should I avoid SideEffect in Compose?▼

Avoid SideEffect for per-frame work or anything that allocates, because it runs on every successful composition commit. Reserve it for thin writes that publish Compose state to a non-Compose system you cannot subscribe to via DisposableEffect.