I have a composable where I want to simulate a changing input with a mutablestateflow. Simply put, I have a composable where you pass in a string field called item description which the composable displays. If the user types in a new description, the mutablestateflow should update to the newly entered description. I'm trying to test out my compoent while developing it, without having to write a full blown viewmodel for it.
This is my composable:
@Composable
fun Foo(itemDescription: String, setItemDescription: (newDescription: String) -> Unit) {
OutlinedTextField(value = itemDescription, onChange = { it -> setItemDescription(it) })
}
And this is how I'm trying to preview it:
@Preview
@Composable
fun PreviewFoo() {
val itemDescriptionMutableStateFlow = MutableStateFlow("SomeInitValue")
val itemDescriptionStateFlow = itemDescriptionStateFlow.asStateFlow()
val itemDescription by itemDescriptionStateFlow.collectAsState()
val itemDescription by itemDescription
Foo(itemDescription = itemDescription, setItemDescription = {
itemDescriptionMutableStateFlow.value = it
})
}
But if I do this, whatever value I type into the the outlined text field, it keeps showing "SomeInitValue" which is the init value for the mutable state flow. This setup works if I use a viewmodel to store the mutablestateflow instead of directly using a mutablestateflow.
How do I simulate a mutablestateflow while testing my component? or what am I doing wrong here? Any help would be awesome!
What appears to be happening is that the Preview function is getting recomposed with every character typed. This is causing itemDescriptionMutableStateFlow
to be reinitialized every time and resetting the value of the text field in the preview. You'll need to remember the MutableStateFlow
to avoid this.
@Preview
@Composable
fun PreviewFoo() {
val itemDescriptionMutableStateFlow = remember {
MutableStateFlow("SomeInitValue")
}
val text by itemDescriptionMutableStateFlow.collectAsState()
Foo(itemDescription = text, setItemDescription = {
itemDescriptionMutableStateFlow.value = it
})
}
You could also use a MutableState
for preview / testing purposes in this particular case.
@Preview
@Composable
fun PreviewFoo() {
var text by remember { mutableStateOf("SomeInitValue") }
Foo(itemDescription = text, setItemDescription = {
text = it
})
}