'Type mismatch in compose state hoisting
I am attempting to get one property to bind between a ViewModel and a @Composable.
I am getting the following error
Type mismatch.
Required:String
Found:MutableState<String.Companion>
I don't understand what I am doing wrong.
//Reusable input field
@Composable
fun MyTextField(
value: String,
onValueChange: (String) -> Unit,
placeHolder: String
) {
OutlinedTextField(
value = value,
onValueChange = onValueChange,
placeholder = {Text(placeHolder)},
)
}
// ViewModel
class MyViewModel : ViewModel () {
var MyVariable = mutableStateOf(String)
}
// stateful comp
@Composable
fun MyScreen(
viewModel: MyViewModel = MyViewModel()
) {
MyContent(
myVariable = vm.myVariable,
setMyVariable = { vm.myVariable = it }
)
}
// stateless Comp
@Composable
fun MyContent(
myVariable: String,
setMyVariable: (String) -> Unit
)
{
Column() {
MyTextField(value = myVariable, onValueChange = setMyVariable, placeholder = "Input Something")
Text("Your variable is $myVariable" )
}
Solution 1:[1]
You are initializing your variable as a MutableState<T> type data-holder.
What you've posted in the question won't even compile but this is what I assume you did in your actual code
var myVar = mutableStateOf ("")
Now, mutableStateOf("") returns a MutableState<String> type object, which you are passing around in your methods.
On the other hand, your methods expect a String type object, not MutableState<String>. Hence, you could either extract the value from your variable and pass that around,
myVar.value
Or do it the preferred way, and use kotlin property delegation.
Initialize the variable like this
var myVar by mutableStateOf ("")
The by keyword acts as a delegate for the initializer and returns a String value instead of a MutableState<T>. This updates and triggers recompositions just as it's other counterpart but is far cleaner in code and keeps the boilerplate to a minimum.
Also, you seem to be pretty new to compose and kotlin, so consider taking the Compose pathway to learn the basics. Just look it up and the first official Android developers link will take you there.
EDIT: FINAL ANSWER
ViewModel
ViewModel{
var v by mutableStateOf ("")
fun setV(v: String) {
this.v = v
}
}
Composable calling site
MyComposable(
value = viewModel.v
onValueChange = viewModel::setV
)
Composable declaration
fun MyComposable (
value: String,
onValueChange: (String) -> Unit
) {
TextField (
value = value
onValueChange = onValueChange
)
}
This is the proper state-hoisting linking where the state variable is updated properly and hence, read well. Also, sir, you'd know what state-hoisting is if you'd actually read through the docs and taken the codelabs. I'm serious, TAKE the codelabs (in the Compose pathway). That's the reason your question was downvoted so many times, because you use terms like state-hoisting as if you understand it, but then you don't have half the implementation that it promotes.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
