https://kotlinlang.org logo
#compose
Title
# compose
c

Colton Idle

03/13/2023, 6:34 PM
I'm trying to pass a lamda down into my composable. The lambda will be null or not depending on some snapshot state. It doesn't seem to work correctly (inside the composable, its not null when it should be null)
Copy code
val buttonClick: (() -> Unit)? =
    if (state.value?.foo == null) {
        null
    } else {
        { //some lambda content }
    }

MyComposable(clickEvent = buttonClick)
Do I need to wrap this in a remember or something?
actually. seems to work fine. AS was loading an old build apparently. yay
f

Francesc

03/13/2023, 7:59 PM
this may be a place where you could use
rememberUpdatedState
c

Colton Idle

03/13/2023, 8:25 PM
TIL rememberUpdatedState exists! I'll see if that helps me at all.
m

myanmarking

03/13/2023, 10:36 PM
You dont need rememberupdatedstate for correctness, altought you could use remember+derivedstate if performance is an issue
s

Stylianos Gakis

03/13/2023, 11:42 PM
You dont need rememberupdatedstate for correctness
You may very well need
rememberUpdatedState
for correctness. In some cases you may be referencing the old lambda if you don’t key properly or don’t use rememberUpdatedState. It can be seen in as simple of an example as this (from a case where I had to do this myself):
Copy code
fun Foo(lambda: () -> Unit) {
  Box() {
    Something(
      Modifier.pointerInput(Unit) {
        detectTapGestures { 
          lambda()
        }
      }
    )
  }
}
If you don’t change this to this
Copy code
fun Foo(lambda: () -> Unit) {
  val updatedLambda = rememberUpdatedState(lambda)
  Box() {
    Something(
      Modifier.pointerInput(Unit) {
        detectTapGestures { 
          updatedLambda()
        }
      }
    )
  }
}
you will be calling the lambda passed on the first composition to Foo, and not the most updated one.
c

Csaba Szugyiczki

03/14/2023, 8:35 AM
@Stylianos Gakis The root cause in your case was the use of Unit as the key parameter for
pointerInput
Modifier. In Material UI element implementations usually the lambda is the key that will be called inside the modifier to prevent using the old lambda reference. Your solution using
rememberUpdatedState
however is more performant as it is not triggering recomposition of the element on which pointerInput is used, so if you change your lambda frequently it might be a better solution. Not sure if not using the lambda for the pointerInput Modifier could lead to “incorrect” behaviour tho 🤔
s

Stylianos Gakis

03/14/2023, 8:49 AM
Yes, I am aware, hence why I said “if you don’t key properly”. And especially in this case for pointerInput, you may need to do this for more than performance reasons. If inside your pointerInput lambda, you are detecting long-press gestures. If after pressing down, but before releasing, your lambda changes, and the entire pointerInput lambda gets recreated, my guess is that it’d cancel the old coroutine, hence lose the information about the start of this long press and you’d miss this interaction. With rememberUpdatedState you are avoiding this problem too. (Which I didn’t test tbh, but I think that it’d be a problem for the reasons I explain)
c

Csaba Szugyiczki

03/14/2023, 8:54 AM
Yeah, that might be true. So many things to keep in mind 🤯
8 Views