A question about `derivedStateOf` for when we want...
# compose
s
A question about
derivedStateOf
for when we want to calculate some result using composable’s parameters vs using local mutableState objects. More in thread 🧵
If I am dealing with local mutableState, to limit updating the value of
result
I’d call
derivedStateOf
and
OtherComp
will only be called when result actually changes.
Copy code
@Composable
fun Comp() {
  var one by remember { mutableStateOf(5) }
  var two by remember { mutableStateOf(8) }
  val result: Boolean by remember { derivedStateOf { one * two < 10 } }
  OtherComp(result) // Pass the result whatever composable
}
But if items come as parameters, and considering this comment in the documentation mentioning that derivedStateOf only works with
State
in this next example we don’t have state but normal parameters. So how do I do the same behavior now?
Copy code
@Composable
fun Comp(one: Int, two: Int) {
  val result = ??
  OtherComp(result)
}
If I just do
val result = one * two < 10
it will work fine, but if the
Comp
composable had more parameters (say
three: Int
, and it changes but not
one
or
two
,
result
will be re-calculated for no reason since it happens in every recomposition of
Comp
(especially bad since I have another variable coming from an animation which changes rapidly) Doing just
val result = derivedStateOf { one * two < 10 }
seems to also be wrong according to this since it will also be recreated on every recomposition since we’re not remembering it. Doing then instead
val result = remember { derivedStateOf { one * two < 10 } }
doesn’t work at all as remember has no keys and derivedStateOf doesn’t know when its inputs change since
one
and
two
are not state objects. Finally doing
val result = remember(one, two) { derivedStateOf { one * two < 10 } }
kind of defeats the purpose of derivedStateOf since we’re keying everything ourselves so we might as well then go with
val result = remember(one, two) { one * two < 10 }
? So is this the way to do things when we want to “reduce” some input to some result when that input comes from the function parameters?
c
What's wrong with
val result = remember(one, two) { one * two < 10 }
here? Aren't those keys to
remember
meant for this exact use case?
s
Yeah I may be overthinking this, but since I was thinking that the two input values change more often than the result, my brain went to this comment immediately which made my brain go “must use
derivedStateOf
“. Also result now no longer is a State object, as
derivedStateOf
would give. but it’s a normal Boolean. Not sure if this has any other implications as well
z
see
rememberUpdatedState
for parameters
s
Right,
rememberUpdatedState
basically turns a
T
into
State<T>
in a sense right? Then it becomes this I assume:
Copy code
@Composable
fun Comp(one: Int, two: Int) {
  val updatedOne by rememberUpdatedState(one)
  val updatedTwo by rememberUpdatedState(two)
  val result: Boolean by remember { derivedStateOf { updatedOne * updatedTwo < 10 } }
  OtherComp(result)
}
Which becomes quite some ceremony over just
Copy code
@Composable
fun Comp(one: Int, two: Int) {
  val result: Boolean = one * two < 10
  OtherComp(result)
}
And I guess at that point it’s a decision making point for the dev if it is worth it in the context, hmm a tough choice imo 🤔
z
Don't use derived state unless you need to for performance.
l
In my opinion, derivedStateOf has quite specific use case more than just caching.
derivedStateOf
can be used for more fine-grained recomposing. In your case, just use
remember(one, two) { ... }
or just
val result = one * two < 10
. If you need to pass some state as-is deep down the tree, and only recompose ones that read that state, (via
state.value
or delegation + reading that variable) use states. If you need to pass the value rather than
State<?>
, using state here is no help. Recomposing is quite smart. Note that
derivedStateOf
can be used outside Compose, and states are not that Compose-specific.