Compose Side Effects Flashcards
UI › Compose Core
- Why must composable functions be free of side effects?
- Because recomposition can happen frequently, run composables in any order, and be discarded entirely. Code that mutates external state directly would run unpredictably. Side effects must instead go through lifecycle-aware effect APIs.
- What does LaunchedEffect do, and what is its key contract?
- It launches a coroutine tied to the composition when it enters, and cancels it when it leaves. If any key passed to LaunchedEffect changes across recomposition, the running coroutine is cancelled and a new one is launched with the new keys.
- How do you run a coroutine from a Button onClick handler in Compose?
- Use rememberCoroutineScope() to get a composition-aware CoroutineScope, then call scope.launch { } inside the click lambda. LaunchedEffect cannot be used because onClick is not a composable scope. The scope is cancelled when the call site leaves composition.
- What problem does rememberUpdatedState solve?
- It lets a long-lived effect always read the latest value of a variable (often a callback) without restarting the effect. You wrap the value, keep the effect's keys stable (e.g. Unit), and the effect references the updated value instead of a captured stale one.
- What is DisposableEffect for and what does it require?
- Side effects that need cleanup, like registering and unregistering an observer or listener. The block must end with an onDispose { } that runs cleanup when the effect leaves composition or a key changes; omitting onDispose is a compile error.
- When does SideEffect run and what is it for?
- It runs after every successful recomposition. Use it to publish Compose-managed state to objects not managed by Compose (e.g. setting an analytics user property). Running such writes after success avoids acting on a recomposition that gets discarded.
- What does produceState return and how does it behave?
- It converts a non-Compose source (Flow, LiveData, RxJava, a suspend load) into Compose State<T>. It launches a coroutine scoped to composition, lets you assign value inside, and supports awaitDispose for non-suspending cleanup. The returned State conflates equal values.
- What is snapshotFlow and when would you use it?
- It converts Compose State reads into a cold Flow. Collected inside a coroutine (often a LaunchedEffect), it emits when the read State changes and conflates consecutive equal values, letting you apply Flow operators like map, filter, and distinctUntilChanged.
- What does passing a constant like Unit or true as a LaunchedEffect key mean?
- The effect never restarts due to key changes; it runs once when entering composition and lives for the whole time the call site stays in composition. It is valid but should be used deliberately, pairing with rememberUpdatedState for values that must stay current.