@Composable fun LoginScene() { val state by producePresenter { Presenter() } Scaffold { Column( modifier = Modifier.fillMaxSize(), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ) { Text(text = "Login", modifier = Modifier.padding(bottom = 16.dp)) TextField( value = state.email, placeholder = { Text("Email") }, modifier = Modifier.padding(bottom = 16.dp), onValueChange = { state.action(LoginAction.UpdateEmail, it) }, ) TextField( value = state.password, placeholder = { Text("Password") }, modifier = Modifier.padding(bottom = 16.dp), onValueChange = { state.action(LoginAction.UpdatePassword, it) }, ) } } } @Composable private fun Presenter(): LoginState { var email by remember { mutableStateOf("") } var password by remember { mutableStateOf("") } return LoginState( email = email, password = password, ) { action, value -> println("$action: $value") when (action) { LoginAction.UpdateEmail -> email = value LoginAction.UpdatePassword -> password = value } } } private sealed interface LoginAction { object UpdateEmail : LoginAction object UpdatePassword : LoginAction } private data class LoginState( val email: String, val password: String, val action: (LoginAction, String) -> Unit, )