Home > database >  Type mismatch in compose state hoisting
Type mismatch in compose state hoisting

Time:05-21

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" )
    }


CodePudding user response:

Replace

MyContent(
    myVariable = vm.myVariable,
    setMyVariable = { vm.myVariable = it }
)

with

MyContent(
    myVariable = vm.myVariable.value,
    setMyVariable = { vm.myVariable.value = it }
)

and you need to define your variable like this

val MyVariable = mutableStateOf<String>("initial value here")

CodePudding user response:

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.

  • Related