I have the following composable function. Its a simple login screen with username, password and submit button.
If username or password fields are empty when the user clicks on the submit button a snackbar will show. However, it works on the first click, but subsequent clicks don't work.
I would think that the button click will force the composable to re-compose and the LaunchEffect key will be true if the snackbar needs to be shown.
@Composable
fun Login() {
var username by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
val scaffoldState = rememberScaffoldState()
var shouldShowSnackBar by remember { mutableStateOf(false) }
println("LoginScreen")
LaunchedEffect(key1 = shouldShowSnackBar, block = {
println("ShouldShowSnackBar")
scaffoldState.snackbarHostState.showSnackbar(
message = "Please enter a username and password",
duration = SnackbarDuration.Short
)
})
Scaffold(
scaffoldState = scaffoldState
) {
Column(modifier = Modifier.fillMaxWidth()) {
OutlinedTextField(
label = {
Text(text = "Username")
},
value = username,
onValueChange = { newUsername ->
username = newUsername
})
OutlinedTextField(
label = {
Text(text = "Password")
},
value = password,
onValueChange = { newPassword ->
password = newPassword
},
visualTransformation = PasswordVisualTransformation())
OutlinedButton(
modifier = Modifier.fillMaxWidth(),
onClick = {
shouldShowSnackBar = username.isEmpty() || password.isEmpty()
println("Button pressed: $shouldShowSnackBar")
}) {
Text(text = "Submit")
}
}
}
}
What you see is expected behavior. In jetpack Compose for recomposition to be triggered the State/MutableState should have new value and composition gets triggered in the scope State/MutableState is read only.
You need to set shouldShowSnackBar to false and invoke block inside LaunchedEffect when shouldShowSnackBar is true.
LaunchedEffect(key1 = shouldShowSnackBar, block = {
if(shouldShowSnackBar){
println("ShouldShowSnackBar")
scaffoldState.snackbarHostState.showSnackbar(
message = "Please enter a username and password",
duration = SnackbarDuration.Short
)
shouldShowSnackBar = false
}
})