LaunchedEffect not triggered when mutableStateOf h...
# compose
a
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:
Copy code
var snackBarMessage: MutableState<String?> = mutableStateOf(null)
    private set
and the set function:
Copy code
fun setSnackbarMessage(msg: String?){
    snackBarMessage.value = null
    snackBarMessage.value = msg
}
Here is my Launcheffect which unfortunately is not getting triggered twice:
Copy code
LaunchedEffect(key1 = viewModel.snackBarMessage.value){ 
    val message = viewModel.snackBarMessage.value
    message?.let {
        scaffoldState.snackbarHostState.showSnackbar(message, "Ok")
    }
}
and on Favorite button click I call:
Copy code
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
also you can
collectAsState
s
Instead of relying on the message itself, you should have a
isDisplayed
variable.
a
with
Copy code
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
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
Yes my approach was actually unnecessary. I now simplay call this from my onclick:
Copy code
scope.launch {
scaffoldState.snackbarHostState.showSnackbar("Added to Favorite", actionLabel = "Ok")
}
and it gets called every time. Thanks guys
c
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()
Copy code
var snackBarMessage: MutableState<String?> = mutableStateOf(null, policy = neverEqualPolicy())
    private set
z
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.
603 Views