Hello, we have a state object `CommonInput` in vie...
# compose
i
Hello, we have a state object
CommonInput
in viewModel, which gets posted to StateFlow and then converted into a
@Composable fun CommonInputDisplay
in our Composable screen.
CommonInput
has a
value
param that gets converted to
MutableState
and used in
TextField
as
value
. The problem is that once it has initialized, we can’t change
TextField
value
by modifying state object from ViewModel anymore. How can we initiate a recomposition with a new value from viewModel by modifying
CommonInput
?
f
CommonInput::value
could be a Compose
State
🤷
Something like
Copy code
class CommonInput(
  val initialValue: String? = null
  ...
) {
  var value by mutableStateOf(initialalue)
    private set
}
i
I know, but can ViewModel be not aware of compose? Ideally it should just post new state and Compose screen just updates
1
y
You could pass it in as a State<X> or lambda. But that feels wrong. Why not make it a val and pass in a new CommonInput instance. If you want to avoid work on recomposition, you could remember other things on the stable fields.
f
Ideally it should just post new state and Compose screen just updates
Sure but in that case the
CommonInput
cannot have mutable properties and cannot mutate iteslf. ViewModel has to do that like yschmke suggests:
make it a val and pass in a new CommonInput instance
y
Exactly. I think you are fighting compose by using mutable fields.
👆 1
i
Right now even if I change all vars to val my screen doesn’t recompose after I post updated state to StateFlow. The values on ViewModel are new, but UI stays the same
f
Try changing the
CommonInput
class
to
data class
i
No change as well with
data class
f
Can you show us how do you emit new values to your state flow and how do you collect it?
i
Copy code
LaunchedEffect(item.value) {
    if (item.value.orEmpty() != inputText) inputText = item.value.orEmpty()
}
I added this after
inputText
initialization and it started to work properly. Is that a correct thing to do here?
f
The
inpuText
should just be
val inputText = item.value.orEmpty()
. No need to create internal state
i
yeah, indeed) thank you!
🎉 1
f
And your
onValueChange
should just call the VM to emit new state - single source of truth
👌 1