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

Chris Fillmore

05/17/2022, 2:31 PM
What’s the right way to include the value of a StateFlow in
derivedStateOf
? (In a VM)
I have a VM like
Copy code
class MyViewModel : ViewModel() {
  val myStateFlow = MutableStateFlow(...)
  val myDerivedState = derivedStateOf {
    // I would like to use the value of myStateFlow here
  }
}
In a
@Composable
I could collectAsState… but I’m not sure what to do outside that context
Thanks for any help
m

myanmarking

05/17/2022, 2:52 PM
val state by remember(viewModel){…collectAsState() }
derivedStateOf { state.sth }
c

Chris Fillmore

05/17/2022, 2:53 PM
That’s in a composable context, whereas I am trying to use derivedStateOf in a VM.
n

natario1

05/17/2022, 2:54 PM
If your VM has a coroutine scope, just collect the flow and pass the value to some mutableStateOf().
c

Chris Fillmore

05/17/2022, 2:55 PM
Oh yeah that makes sense. Maybe I’ll write an extension to do that
Thanks for responding everyone
m

myanmarking

05/17/2022, 2:55 PM
derivedStateOf only works on another state variables. Why not use myStateFlow.map{ … }. You dont need derivedState in viewModel
c

Chris Fillmore

05/17/2022, 2:57 PM
My actual VM uses derivedStateOf with a few `State`s and I wanted to also use a
StateFlow
. Is there a reason you suggest I shouldn’t use derivedStateOf in a VM?
m

myanmarking

05/17/2022, 2:59 PM
yes. derivedStateOf is compose related. You can, but should not use it in viewModel. Besides, you can use flows for anything related to compose state, so why would you use mutableState/derivedState in viewmodel anyway
c

Chris Fillmore

05/17/2022, 3:03 PM
State
is part of compose
runtime
, so I don’t see it makes a difference whether I have a dependency on the compose runtime vs coroutines/flow. I would argue you should use whatever satisfies your use case. But I’d be open to hearing arguments otherwise.
n

natario1

05/17/2022, 3:05 PM
It’s totally fine. I’d just try to stay consistent with your choice across your VMs.
👎 1
m

myanmarking

05/17/2022, 3:26 PM
The more abstractions the more complex your code becomes. You already use flows in viewModel, you dont need derivedStateOf or mutableStateOf in the mix
👍 2
z

Zach Klippenstein (he/him) [MOD]

05/17/2022, 11:05 PM
Use whatever makes sense for your architecture. There are pros/cons to StateFlow/snapshot state other than which library artifacts they come from, evaluate based on those first. Snapshot state is a really powerful thing that might end up simplifying a lot of code if you use it pervasively enough.
c

Chris Fillmore

05/18/2022, 12:10 AM
Yeah I do like the simplicity of compose State. I’ve been trying to use it more lately in lieu of StateFlow, but I find I’ll reach for StateFlow if I need effects via onEach in non-compose context
t

Tash

05/18/2022, 1:52 AM
We do use Snapshot state in our VMs in some cases (VMs differ drastically, and we try to approach on a case-by-case basis) In this case, we might drop the `StateFlow`:
Copy code
class MyViewModel : ViewModel() {
  val myState = mutableStateOf(...)
  val myDerivedState = derivedStateOf {
    // Some function of myState...
  }
  ...
  // Set myState.value in the same place you updated StateFlow
}
This is the only way I can think of if you really want to expose Snapshot state, because otherwise, there is no way to cross the
StateFlow
/Snapshot state boundary from a non-Compose context such as VM
z

Zach Klippenstein (he/him) [MOD]

05/18/2022, 3:18 AM
if I need effects via onEach in non-compose context
Triggering effects on state change is always risky, since states can be conflated with both approaches. But just as you can go from a
StateFlow
to a
State
via
collectAsState
, you can always go from a
State
to a
Flow
with
snapshotFlow
.
👍 1
c

Chris Fillmore

05/18/2022, 11:11 PM
The effects I have in mind are of the “save changes” sort where conflation is desired. But I know what you mean otherwise 👍
43 Views