Am I understanding it correctly that I always need...
# compose
m
Am I understanding it correctly that I always need to figure out and provide the correct keys to
remember
around
derivedStateOf
? I believe the compiler plugin doesn’t derive them for me, does it? If so, is there a plan for a combined
rememberDerivedStateOf
of some kind which does it?
s
How would you prefer to make this work exactly? If you’re only reading state objects, you do not need to use them as keys, since inside
derivedStateOf
their state will be automatically observed. If you’re at the same time using some value from a non-state variable (say a
param: T
as part of your composable) then that is not a state object, hence you need to key it. Would you want this
rememberDerivedStateOf
to magically try to find out if your objects are state objects or not?
m
The Compose compiler plugin internally already tracks captured values and records them for `@Composable`s, so yes, I would expect exactly the same internally in
rememberDerivedStateOf
cc @shikasd
can you magically make it so we don’t need to use state objects at all? That’d be even easier
Not sure I agree, because having a state object is the whole point of it, isn’t it? Otherwise we could just use
remember
(minus the automatic dependency tracking we’re talking about here)
j
I know, just joking
s
Hmm I see, I personally like the control I get from the current behavior, no surprises hidden this way. And in general that’s how I feel working with compose, things are pretty consistent as to which parts are “magic” and which parts aren’t. If this suddenly blurs the line between those two worlds I think it’d be harder to reason about than what we currently have. I could be wrong of course, but those are my first thoughts about what you are suggesting here.
m
Those are good points. The reason why I’m asking is that I find
derivedStateOf
pretty hard to use correctly right now, and I can’t think of a better way to improve it Maybe that design is even on purpose to nudge people into doing more recalculations instead of cluttering the runtime with overhead from tracking and invalidating calculation results, but I don’t know that
s
I wouldn't say that design is on purpose, but any kind of "automatic" memoization is pretty hard to debug, so we try to avoid that in places where
remember
is already used.
What kind of patterns you find hard to use
derivedStateOf
for?
m
I want to migrate a large codebase from a different custom caching implementation to
derivedStateOf
, and the previous implementation is based on exactly such a compiler plugin which automatically wraps the calculation with the captured values as keys. The patterns are always complex and expensive calculations, which means the code inside them might capture a lot of references and it will be tedious to extract all of them manually. I believe such a pattern is the exact point where
derivedStateOf
should help, but the manual management of `key`s makes it hard for us to switch.
s
It kinda depends, because you don't want to recreate
derivedStateOf
that often to ensure caching works. In some cases, it makes more sense to convert some of those changing values to
mutableStateOf
instead.
m
And write to the mutable states during composition?
s
That's not ideal, but you can do that If the derived state invalidates a large portion of composition, that might be faster
m
Hmm, OK. Will play around with that a little. Thanks!
j
I also think
remember { derivedStateOf { } }
is a tricky API to use correctly. I'm not sure some
magicDerivedStateOf { }
that is invalidated both by changes to the state objects it reads outside the composition and by changes to the params it reads that are local to the current composition would be easier to understand, but I think better lint / code inspection tools in the IDE would go a long way here. E.g. something as simple as warning when I'm reading a param from the composition but not using it as a key to remember would catch so many simple mistakes I've made.
s
I hope we can figure out a way to avoid adding the equivalent of
exhaustive-deps
from eslint here :)