I have a list of composable functions that can be ...
# compose
e
I have a list of composable functions that can be mutated, and I'm running into issues where removing an item causes all the items to the right of it in the list to be disposed. I can fix this by using the
key
function, but my use case doesn't guarantee that the keys will be unique. I'm trying to solve this with
movableContentOf
that I got/modified from here but when I use that, all of my items are immediately disposed. I'm not sure why they're disposing, but I'm also not sure why this would work in the first place.
Copy code
val entries by entriesUpdateFlow.collectAsState(
  // it's weird but effective way of getting initial value in this case
  initial = entriesUpdateFlow().value.map(Entry.Companion::fromBaseEntry) 
)

val movableEntries = entries.map { entry ->
  movableContentOf {
    Renderer(entry)
  }
}

entries.forEachIndexed { index, _ ->
  movableEntries[index]()
}
f
my use case doesn't guarantee that the keys will be unique
What is this usecase? Can't you just "make up" unique IDs? Or maybe use a compound key with multiple properties.
e
Here's the change I made to address this - https://github.com/eygraber/portal/pull/282 The key is supplied by the user of the library and there could be a use case where they want to add more than one of a certain key, and that key is implemented as an
object
.
f
So
entry.key
is more of a "type" of entry rather than identification of entry. Is that correct?
If that assumption is true, maybe you can count the number of entries with the same type and give each "duplicate" an unique ID. Something like incrementing the counter of entries with the same key and give each entry the current counter value and increment.
And back to the initial question
Copy code
val movableEntries = entries.map { entry ->
  movableContentOf {
    Renderer(entry)
  }
}
This will be "immediately disposed" because you have to remember the
movableContentOf
or store it outside of the composition.
e
Because this library is meant to be generic, it's hard to pin down the functionality of the key. Some might use it for typing, some for identification, and some for both. I'll try out remembering the
movableContentOf
, thanks!
f
Then you can be more transparent of the usage of
entry.key
and pass the uniqueness contract to the user.
e
True, I've been thinking of how to present that. Mostly made simpler by the fact that it's unlikely that anyone will ever use this besides me 😅
you have to remember the
movableContentOf
or store it outside of the composition.
For the sake of understanding I've been trying to make
movableContentOf
work for me, but I think I'm missing something. In the example I linked above it doesn't look like the
movableContentOf
is remembered or stored outside of the composition. I was able to get my use case to work by using a
Map
approach where I store the
movableContentOf
outside of the composition keyed by my
Key
. But to me that seems functionally the same (and much more complex) than using the
key
function. I'm trying to do something similar to the linked example. This was the closest I could get (still stuck using my key), but when removing the first entry in the list, all the other entries get disposed. I changed my
Renderer
function to take the entry's composable as a param (wrapped in the
movableContentOf
) because the
Renderer
is also responsible for indirectly mutating the list, which seemed to cause several state issues.
Copy code
val entries by entriesUpdateFlow.collectAsState()

val movableEntries = entries.map { entry ->
  remember(it.key) { movableContentOf { it.Render() } }
}

entries.forEachIndexed { index, entry ->
  RenderEntry(entry, movableEntries[index])
}
Maybe @Jorge Castillo has some ideas? The example came from his blog post.