// ViewModel owns the state @Composable fun TopLevel() { val state by viewModel.state.observeAsState() TextField( value = TextFieldValue(text = state.username), onValueChange = { viewModel.setUsername(it.value) } ) TextField( value = TextFieldValue(text = state.password), onValueChange = { viewModel.setPassword(it.value) } ) Button(onClick = { viewModel.login() }) { Text("Login") } } // view state is handled by view @Composable fun TopLevel() { var username by state { "" } var password by state { "" } TextField( value = TextFieldValue(text = username), onValueChange = { username = it.text } ) TextField( value = TextFieldValue(text = password), onValueChange = { password = it.text } ) Button(onClick = { viewModel.login(username, password) }) { Text("Login") } }