Reputation: 6835
I'm trying to understand why my SnackBar does not show second time, I'm propagating the snackbar message and error boolean values from my composables, I'm taking this data and emiting a single snackbar but it works first time and not second time with the same message even if I set the message to null.
When I go to my register screen I emit an error message if the e-mail is already present in the DB, then if I trigger again the same message, nothing happens and the snackbar does not appear, any ideas ?
setContent {
var snackBarMessage: String? by remember { mutableStateOf(null) }
var isError by remember { mutableStateOf(false) }
val snackbarHostState = remember { SnackbarHostState() }
CryptoTheme {
Scaffold(
scaffoldState = scaffoldState,
snackbarHost = {
SnackbarHost(hostState = snackbarHostState) { data ->
Snackbar(
snackbarData = data,
backgroundColor = if (!isError) GreenProfit else Color.Red,
contentColor = Color.White
)
}
},
bottomBar = { BottomBarNavigation(navController = navController) },
backgroundColor = Color.Black
) {
NavigationGraph(
modifier = Modifier.padding(bottom = it.calculateBottomPadding()),
navController = navController,
showSnackBarMessage = { message, showError ->
isError = showError
snackBarMessage = message
}
)
LaunchedEffect(key1 = snackBarMessage) {
if (snackBarMessage != null) {
snackbarHostState.showSnackbar(
message = snackBarMessage ?: ""
)
snackBarMessage = null
}
}
}
}
}
Inside NavigationGraph I have multiple composables that reuse this way of propagating the message and error to the scaffold to show the snackbar
NavigationGraph(showSnackBarMessage: (message: String, isError: Boolean)) {
Navhost(...) {
composable(route) {
RegisterComposable(showSnackBarMessage)
}
}
and from the composable
RegisterComposable(showSnackBarMessage: (message: String, isError: Boolean)){
when(uiState.signUpError) {
showSnackBarMessage("E-mail already in use", true)
}
Upvotes: 5
Views: 1384
Reputation: 161
This is a bug in kotlinx-coroutines:1.8.0-RC
you can simply fix it by upgrading to 1.8.0-RC2
.
If you are using Compose multiplatform it is fixed in version 1.6.0-beta01
of the compose plugin or you can downgrade to 1.5.11
where the issue does not happen.
Upvotes: 0
Reputation: 410
Your snackbar is not shown because the message
and isError
are not changed. Compose will only get recomposed when its referenced values have changed.
Snackbar is a kind of one-time event. So you need to provide it as an effect
Recommend: combine your message
and isError
into a data model
data class SnackBarAction(
val uid: Long = System.currentTimeMillis(),
val text: String,
val isError: Boolean,
)
On your compose layout
val (stateOfSnackBarAction, setSnackBarAction) = remember {
mutableStateOf<SnackBarAction?>(null)
}
val scaffoldState = rememberScaffoldState()
val coroutineScope = rememberCoroutineScope()
Scaffold(scaffoldState = scaffoldState) {
LaunchedEffect(key1 = stateOfSnackBarAction) {
stateOfSnackBarAction ?: return@LaunchedEffect
scaffoldState.snackbarHostState.showSnackbar(
message = stateOfSnackBarAction.text,
backgroundColor = if (stateOfSnackBarAction.isError) Color.Red else GreenProfit,
)
...
}
...
To show snackbar
Button(
onClick = {
coroutineScope.launch {
val current = System.currentTimeMillis()
setSnackBarAction(SnackBarAction(
uid = current,
text = "Your message here",
isError = true/false
))
}
}
Upvotes: 0