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

Sterling Albury

11/30/2023, 7:18 PM
I’m working with the compose runtime library and I’ve got a custom Modifier function that takes a mutable list, but I’m not getting recompositions when I update the list. I’m only seeing recompositions if I create a new instance of the list. I’ve tried using a mutable state list but that doesn’t seem to help. Is this expected? my modifier function looks like
Copy code
fun Modifier.foo(
    fooList: List<Foo>
): Modifier = this.then(
    FooModifierElement(fooList)
)
my composable content:
Copy code
var fooList by mutableStateOf(mutableListOf<Foo>())
setContent {
    CustomComposable(modifier = Modifier.foo(fooList))
}
if I just add something to the list, nothing happens, but if I assign
fooList
to a new list instance, then it recomposes. Is there a way to be able to just update the list and trigger a recomposition?
a

Alexander Maryanovsky

11/30/2023, 7:22 PM
Yes, this is expected. The composition doesn’t know that you changed the list.
You need to either pass a new list whenever it changes, or use
SnapshotStateList
SnapshotStateList
notifies the composition whenever any of its values changes.
s

Sterling Albury

11/30/2023, 7:31 PM
ok, right on. thanks
i had actually tried this with
mutableStateListOf
but don’t see the recompositions.
a

Alexander Maryanovsky

11/30/2023, 7:49 PM
Copy code
@Composable
fun Items(list: List<Int>) {
    Column {
        for (item in list) {
            Text(item.toString())
        }
    }
}

setContent {
    val list = remember { mutableStateListOf(0) }
    Column {
        Button(onClick = { list.add(list.size) }){
            Text("Click me")
        }
        Items(list)
    }
}
s

Sterling Albury

11/30/2023, 8:12 PM
I’m defining my list outside of
setContent
so I’m not able to use
remember
…maybe this is part of my problem
a

Alexander Maryanovsky

11/30/2023, 8:14 PM
No, this will work the same:
Copy code
@Composable
fun Items(list: List<Int>) {
    Column {
        for (item in list) {
            Text(item.toString())
        }
    }
}

val list = mutableStateListOf(0)

@Composable
fun App() {
    Column {
        Button(onClick = { list.add(list.size) }){
            Text("Click me")
        }
        Items(list)
    }
}
s

Sterling Albury

11/30/2023, 8:18 PM
hmm..for some reason I’m not seeing it work in my code. let me see if I can create a sample project that shows more of how i have things set up
z

Zach Klippenstein (he/him) [MOD]

12/01/2023, 12:01 AM
If you’re only reading the list inside your modifier, then recomposition isn’t involved. Something needs to be observing snapshot reads in your modifier in order to invalidate itself when the list changes. Unlike many of the
Modifier.foo
factory functions, many of the
Modifier.Node
interfaces don’t observe snapshot reads, so you will need to wire that up yourself.
2 Views