Monica
Monica

Reputation: 436

How use mutable object in compose?

I try to use mutable object in compose function:

@Composable
fun TextFieldComponent(
    name: MutableState<String>,
    nameErrorState: MutableState<Boolean>,
    modifier: Modifier = Modifier
)

I use MutableState because it is field for input data. It works good. But I check my code with detectAll And it shows me error: Using mutable objects as state in Compose will cause your users to see incorrect or stale data in your app. Mutable objects that are not observable, such as ArrayList or a mutable data class, cannot be observed by Compose to trigger recomposition when they change. See https://twitter.github.io/compose-rules/rules/#do-not-use-inherently-mutable-types-as-parameters for more information. [MutableParams]

I have read info from this link but still don't understand, how should I use it.

Upvotes: 1

Views: 692

Answers (2)

Samuel Robert
Samuel Robert

Reputation: 11082

As a standard rule, you shouldn't have a mutable state as a parameter to a composable function. Because, in Kotlin arguments are immutable by design. If you wish to change the state of a variable within the composable, you can have muttable state of local variable for that.

@Composable 
fun Profile(initName: String) {
    var name by rememberSaveable { mutableStateOf(initState) }

    TextFieldComponent(
        name,
        nameErrorState = name.isEmpty(),
        modifier = Modifier.padding(top = 16.dp),
        onNameChanged = { newValue -> name = newValue})
    }
}

Upvotes: 2

Mike
Mike

Reputation: 2705

You should pass the data and callback to change it:

@Composable
fun TextFieldComponent(
    name: String,
    nameErrorState: Boolean,
    modifier: Modifier = Modifier,
    onNameChanged: ((String) -> Unit) = {}
)

This way TextFieldComponent is always redrawn when the name is changed. You can also pass name as mutable data from outer Composable:

@Composable
fun Content() {
    var name by remember { mutableStateOf("") }
    TextFieldComponent(
        name,
        nameErrorState = name.isEmpty(),
        modifier = Modifier.padding(top = 16.dp),
        onNameChanged = { newValue -> name = newValue})
}

Upvotes: 2

Related Questions