min
07/20/2026, 8:11 AMLaunchedEffect restarts when one of the key parameters changes. However, in some situations you might want to capture a value in your effect that, if it changes, you do not want the effect to restart. In order to do this, it is required to use rememberUpdatedState to create a reference to this value which can be captured and updated. This approach is helpful for effects that contain long-lived operations that may be expensive or prohibitive to recreate and restart.
> For example, suppose your app has a LandingScreen that disappears after some time. Even if LandingScreen is recomposed, the effect that waits for some time and notifies that the time passed shouldn't be restarted:
> @Composable
> fun LandingScreen(onTimeout: () -> Unit) {
>
> // This will always refer to the latest onTimeout function that
> // LandingScreen was recomposed with
> val currentOnTimeout by rememberUpdatedState(onTimeout)
>
> // Create an effect that matches the lifecycle of LandingScreen.
> // If LandingScreen recomposes, the delay shouldn't start again.
> LaunchedEffect(true) {
> delay(SplashWaitTimeMillis)
> currentOnTimeout()
> }
>
> /* Landing screen content */
> }min
07/20/2026, 8:14 AMrememberUpdatedState to create a reference to this value which can be captured and updated
This left me under the impression that it’ll remember the first value it was composed with throughout the rest of the lifetime of the @Composable instance.
> This will always refer to the latest onTimeout function
Which this seems to contradict.
> To make sure that the onTimeout lambda always contains the latest value that LandingScreen was recomposed with, onTimeout needs to be wrapped with the rememberUpdatedState function
Isn’t the whole point of @Composable functions that they run again when a state they depend on has changed? Every parameter of a composable sees the latest argument the composable was called with, does it not? So why do I suddenly need rememberUpdatedState?Stylianos Gakis
07/20/2026, 8:22 AMStylianos Gakis
07/20/2026, 8:27 AMmin
07/20/2026, 9:31 AMwhich part of this makes you think it will be the same for the rest of the lifetime?@Stylianos Gakis I didn’t really understand what the docs meant by ‘updated’, because 1. that’s not how remembering usually works, and 2. so far I’ve not had to do anything to provide
@Composable functions with ‘updated’ arguments aside from calling it again with updated values.
But doing so would restart the effect and then also restart the delay function there. That's why this technique is used here.So it’s like remembering and capturing a cell to update?
val currentOnTimeOut by remember {
object { var current = onTimeOut }
}
currentOnTimeOut.current = onTimeOut
LaunchedEffect(true) {
// ...
currentOnTimeOut.current()
}
So the object is persisted throughout the rest of the @Composable node lifetime and shared between the body and the LaunchedEffect?Stylianos Gakis
07/20/2026, 11:01 AMmin
07/20/2026, 11:37 AM{ arg ->
val state = remember { mutableStateOf(/* initial */ arg) }
state.value = /* latest */ arg
state
}
I see, thanksStylianos Gakis
07/20/2026, 11:42 AMefemoney
07/23/2026, 8:56 AMChuck Jazdzewski [G]
07/30/2026, 9:08 PMrememberUpdatedState() exists at all it is a pattern that you can subtly get wrong. The things it does is important. 1) It remembers the mutableStateOf() 2) the state object it returns is always the same state object, 3) the state is always updated with parameter value passed in. These appear obvious but we saw wrong versions of this often enough to create a helper.