If I have a transitive `remember` 's which are ini...
# compose
d
If I have a transitive
remember
's which are initialized with values of
State<T>
, will they be re-memoized on state changes? This sounds quite entangled, that's because I need some clarity on this 🙂 Please see thread, with bottom-sheet related example.
Copy code
@Composable fun Content(state: State) {
  val scaffoldState = rememberBottomSheetScaffoldState(
    bottomSheetState = rememberBottomSheetState(state.positionsSheetState)
  )
  BottomSheetScaffold(scaffoldState, ...)
}
In the example above
state: State
itself comes from
mutableStateOf<State>()
, it's its
.value
I want to initialize bottomSheet to be
state.positionsSheetState = Expanded
, but then I want to influence it while changing
state.positionSheetState
to other values. is this correct? Somehow I look at this and think that
Compose
will track
state.positionsSheetState
and re-evaluate `remember`'s? Or will it only memoize once, on first composition?
v
No, it will not update bottom sheet state, since `rememberBottomSheetState`’s first argument is
initialValue
And
remember { mutableState.value }
will not work either. But
derivedStateOf { mutableState.value }
will work. Thought it’s no good in your case
What you need is to synchronize bottom sheet state with your
state.positionsSheetState
which manifests the fact that you have two sources of truth about bottom sheet state. I had some chat with googlers in some thread about how to approach this and we haven’t quite reach a common ground on this, I think. I’ll just share my solution for this, which works for me, and you decide, if you need it or not. It’s for
DrawerState
but the similar approach should work for any of those kind of states (drawer, backdrop, bottom sheet, etc.)
Copy code
@Composable
private fun drawerState(drawerScreenState: DrawerScreenState, dispatch: Dispatch): DrawerState {
    val drawerValue = if (drawerScreenState.isOpened) DrawerValue.Open else DrawerValue.Closed
    return rememberDrawerState(initialValue = drawerValue, confirmStateChange = { newDrawerValue ->
        when (newDrawerValue) {
            DrawerValue.Closed -> dispatch(CloseDrawer)
            DrawerValue.Open -> dispatch(OpenDrawer)
        }
        false
    }).apply {
        LaunchedEffect(drawerValue) {
            when (drawerValue) {
                DrawerValue.Closed -> close()
                DrawerValue.Open -> open()
            }
        }
    }
}
This will handle the initial state and updates from the external source of truth and then return updated state which then you can plug into
rememberScaffoldState
or whatever similar
d
Yes, that part i did the same (or similar) — I just use the
confirmStateChange
+ launched effect. My question was more about using
state.someField
to initialize
remember
transitively and where
state
is in turn
State<T>
— knowing that Compose tracks reads to
State<T>
I thought, would it somehow affect memoization.
v
Compose can call only
@Composable
functions and lambdas when recomposing, so no, it will not track access in
remember
since passed lambda is not
@Composable
d
oh, nice, thanks