I’m seeing some interesting behavior with `remembe...
# compose
j
I’m seeing some interesting behavior with
remember
in a few of our screens. Essentially I have multiple “Screen” level composables which store a remembered value in a val and the val has the same name in all of those composables. This results in the remembered value actually being shared across these screens as I navigate between them. Is this expected? 🧵
So as an example I have some composables that are like this:
Copy code
@Composable
fun Screen1(viewModel: Screen1ViewModel) {
   val isAuthenticated = remember { viewModel.isAuthenticated.value }
   // ...
}

@Composable
fun Screen2(viewModel: Screen2ViewModel) {
   val isAuthenticated = remember { viewModel.isAuthenticated.value }
   // ...
}
These screen composables are called from the NavHost composable definitions directly based on which screen we’ve navigated to.
I was under the impression that remember is scoped to the composable, but that doesn’t seem to be the case. My theory from what my knowledge of how compose works is that remember is actually only scoped to composables which result in a node being added to the UI tree. So These are actually added to the NavHost node or maybe something above that in our tree. Then I think remember uses the val name as the key for storing the remember value on the node. So since these vals are the same name and they end up on the same parent node, they end up being shared.
Is that correct or am I off base?
I tested this out by changing the name of the vals between the screens and that results in them no longer being shared which confirms my thinking.
To solve it I ended up setting a unique key for the remember function because I wanted it to be more explicit than the val name differentiating them
d
First of all this value is coming from the ViewModel, why does it need to be remembered? Does the ViewModel not provide enough persistence?
Second, it looks like your boolean is stored in a flow, can you not use collectAsState?
j
All good questions
Essentially I only care about the flow value on the initial composition. There’s business logic reasons we need to work through as to why collectAsState causes issues for us in this case
We’re basically checking if the user is authenticated so we can direct them to login on the initial composition, but if the user logs out, we don’t want this logic to be triggered while the screen is displayed.
That’s all stuff I can work through and sort out though. Mainly curious about the remember mechanics. For this exercise we can just assume the value is a constant that’s different on the different screens
d
What about using a LaunchedEffect?
j
Yeah, that would also work around this issue/behavior
d
Seems a bit more intuitive too?
j
I think the most intuitive thing is to just set this state on the VM on init and read it from there without remember or launchedEffect like you said. That’s probably what we’ll end up doing
I’m just curious if I’m correct about how remember works
d
Probably default key is the property name.
i
The default key is the position in composition (you can google search for compose slot table for more info)
d
That makes more sense
i
Are you using
NavHost
or
AnimatedNavHost
? They are based on different things (
Crossfade
and
AnimatedContent
, respectively) and will exhibit different behavior because of that - I suspect this isn't ever possible in the later
j
I’m using NavHost