LaunchedEffect(key) { } runs a coroutine when its call enters the composition, restarts it when the key changes and cancels it on leave. LaunchedDemo loads the current book; Next book changes it:
LaunchedEffect(book.id) { // a new coroutine whenever the key changes
Log.d(FX, "load ${book.id}: start")
try {
delay(1500) // stands in for a network call
Log.d(FX, "load ${book.id}: done")
} catch (e: CancellationException) {
Log.d(FX, "load ${book.id}: cancelled"); throw e // always rethrow cancellation
}
}After the first load, Next book is tapped twice, half a second apart:
D/BookNestFx: load 1: start D/BookNestFx: load 1: done D/BookNestFx: load 2: start D/BookNestFx: load 2: cancelled D/BookNestFx: load 3: start D/BookNestFx: load 3: done
React 7,897 needs an AbortController for this race; here structured concurrency (Structured Concurrency) cancelled the stale load. LaunchedEffect(Unit) runs once, like [].