https://kotlinlang.org logo
Title
a

Aaron Waller

06/01/2022, 8:21 AM
LaunchedEffect not triggered when mutableStateOf has same value? I want to display a snackbar message when the user clicks on “Favorite Post” It works fine the first time but after that it is not getting triggered anymore. Here is my snackBarMessage State in ViewModel:
var snackBarMessage: MutableState<String?> = mutableStateOf(null)
    private set
and the set function:
fun setSnackbarMessage(msg: String?){
    snackBarMessage.value = null
    snackBarMessage.value = msg
}
Here is my Launcheffect which unfortunately is not getting triggered twice:
LaunchedEffect(key1 = viewModel.snackBarMessage.value){ 
    val message = viewModel.snackBarMessage.value
    message?.let {
        scaffoldState.snackbarHostState.showSnackbar(message, "Ok")
    }
}
and on Favorite button click I call:
viewModel.setSnackbarMessage("Added to Favorite")
Eventhough I set the snackBarMessage to null it is not getting retriggered, only if the string message is different from the one before. I want to show the snackbar every time the user clicks on the button and not just the first time
o

oianmol

06/01/2022, 8:26 AM
also you can
collectAsState
s

ste

06/01/2022, 8:34 AM
Instead of relying on the message itself, you should have a
isDisplayed
variable.
a

Aaron Waller

06/01/2022, 8:35 AM
with
LaunchedEffect(key1 = viewModel.snackBarMessage)
its not getting triggered at all. I changed my mutableStateOf to a MutableStateFlow and collected it as a state but its still the same behaviour, it just gets called the very first time
s

ste

06/01/2022, 8:38 AM
Also, I never used material's snackbar, but I guess your
snackBarMessage
is useless. You can directly call
scaffoldState.snackbarHostState::showSnackbar
inside your clickable or whatever
a

Aaron Waller

06/01/2022, 8:54 AM
Yes my approach was actually unnecessary. I now simplay call this from my onclick:
scope.launch {
scaffoldState.snackbarHostState.showSnackbar("Added to Favorite", actionLabel = "Ok")
}
and it gets called every time. Thanks guys
c

Casey Brooks

06/01/2022, 2:01 PM
I don’t think it’s not that the
LaunchedEffect
isn’t triggering properly, it’s that the
mutableStateOf
is optimizing itself when it sees that the new value is the same as the old value.
mutableStateOf()
by default uses
structuralEqualityPolicy()
to do that optimization, but you can use a different policy such as
referentialEqualityPolicy()
or
neverEqualPolicy()
to tweak it so that it triggers when you expect it should. In this case, to have it trigger twice on
null
, you’ll need the
neverEqualPolicy()
var snackBarMessage: MutableState<String?> = mutableStateOf(null, policy = neverEqualPolicy())
    private set
z

Zach Klippenstein (he/him) [MOD]

06/01/2022, 4:21 PM
Directly invoking the
showSnackbar
function from your event handler is the correct approach. Sure you can use
neverEqualPolicy
to maybe make this work, but there’s a reason that path has extra friction. State, by definition, is idempotent, so most types for working with state (
MutableState
,
MutableStateFlow
) automatically conflate equivalent values.