Youssef Shoaib [MOD]
04/14/2024, 11:29 AMremember { derivedStateOf(block) }.let {
Snapshot.withoutReadObservation { it.value }
}
seems to do the trick and save me many headaches and complex code. Please let me know though if that's a bad approach.
I'm trying to create an "effect" block: a Composable that returns R
that only recalculates its value if the states read within it previously have changed, but it only does that recalculation at the point of time that it's called at.
To state the problem concisely, I want to capture all the `StateObject`s read inside a block, and capture the state of those objects when they are read. Then, I want to later compare the state I captured with the current state according to the snapshot and hence determine if the previous calculation is now invalid. This is like a remember
but based on the states read inside instead of explicit keys
This is distinctly different from a derivedStateOf
because seemingly the latter updates itself when one of its dependencies are updated sometimes before its value
is read.
This works:
private val StateObject.currentRecord: StateRecord
get() = firstStateRecord.withCurrent { it }
@Composable
public fun <R> effect(block: () -> R): R {
var stateToRecord by remember { mutableStateOf<Map<StateObject, StateRecord>?>(null) }
var result by remember { mutableStateOf<R?>(null) }
if (stateToRecord?.any { (state, record) -> state.currentRecord != record } != false) {
stateToRecord = buildMap {
Snapshot.observe(readObserver = {
put(
it as StateObject,
it.currentRecord
)
}) {
result = block()
}
}
}
return result!!
}
There has to be a better way to do this, right? I'm a Compose newbie and just experimenting academically, so apologies for the abstract nature of this questionYoussef Shoaib [MOD]
04/14/2024, 12:18 PMvalue
calls, or otherwise restrict it to only update when I allow it toshikasd
04/14/2024, 2:46 PM