derivedStateOf{} vs remember{} with keys — The difference

These two might seem to achieve the same behavior, but there are differences!

The Android Developer
4 min readNov 24, 2022

In this short article I will clearly explain the difference between derivedStateOf{} and using remember{} with keys. After reading this article, you will have a very clear idea of the difference between them.

Pre-requisites

To understand this article, you must be familiar with the following concepts:

  • Creating and remembering state in compose
  • How state relates to recomposition
  • Recomposition

remember{} with keys

The remember{} function is used to, as the name implies, remember state in the composition. This helps the composable function to remember the previous value when it is recomposed. The remember function can also take a number of arguments known as “keys”. A key can be any value that can change over time. The function can take more than one key as argument. In compose, we use states to represent values that can change over time. When any one of the keys passed to the remember block changes value, the trailing lambda of the remember block gets re-executed. This becomes very handy if a state needs to be remembered and then re-calculated only when another state changes.

For example, let’s assume you want to filter a list when the filter is changed by the user. You can create a remember block that takes in the currently selected filter as a key. The filtered list is recomputed only when the currently selected filter changes.

val filteredTasksByName by remember(currentlySelectedFilter) {
tasks.filter{ it.name == currentlySelectedFilter.filterName }
}

derivedStateOf

Although, at first glance, derivedStateOf might seem as a better version of remember, it is mainly used for performing another important functionality. It is true that the trailing lambda of derivedStateOf gets recomputed when any state value referenced within that trailing lambda gets changed. This removes the need for specifying the keys explicitly.

@Composable
fun someComposableFunction(){
.
.
.
var stateVariable by remember {
derivedStateOf {
// any state that is read within this block will cause
// this block to be re-executed when that state changes value.
}
}
.
.
.
}

As mentioned before, it is used to perform another important fuctionality — reducing unnecessary recompositions. In the case of remember the lambda gets recomputed even if the key that changed was set to the same value it was set previously. I’m going to take the example that I used in my other article, where I go in detail about derivedStateOf. If you want an in-depth guide on what derivedStateOf is and when it should be used, checkout that article. Let’s say we want to display a “scroll to top” FAB (Floating Action Button) when the user has scrolled past the 3rd item in a lazy list. If we were to use remember{}, we might do something like this.

@Composable
fun someComposableFunction(){
.
.
var isScrollUpFabVisible = remember(lazyListState.firstVisibleItemIndex){
lazyListState.firstVisibleItemIndex > 3
}
.
.
if(IsScrollUpFabVisible){
/* Display the floating action button*/
}
.
.
}

This works, but, it results in lots of redundant recompositions.The lazyListState.firstVisibleItemIndex property changes very frequently. This makes sense because the index of the first visible item keeps changing as the user scrolls the list. This results in the composable, getting recomposed as long as the user keeps scrolling! If we look at the state change as a stream of data, then we would have something like this — false, false, false, false, true, true, true.. and so on. Wouldn’t it be better to recompose only when the state moves from true to false and vice versa? Well, that’s what derivedStateOf does. It looks at the new value and compares it to the old value. If both are the same, then, it wouldn’t change the value of the state. Since the value of the state doesn’t change, the composable that reads the state is not recomposed. Thereby, removing unnecessary recompositions. This is the main functionality of derivedStateOf and it should be used when the composable that uses a state needs to compose less frequently that the rate at which the state changes. The same functionality can be achieved in a much more efficient manner using derivedStateOf as follows:

@Composable
fun someComposableFunction(){
.
.
var isScrollUpFabVisible by remember {
derivedStateOf { lazyListState.firstVisibleItemIndex > 3}
}
.
.
if(IsScrollUpFabVisible){
/* Display the floating action button*/
}
.
.
}

Wrap up

And there you go🎉! That’s the difference between derivedStateOf and remember with keys . Here’s a bonus, remember is a composable function and derivedStateOf is a normal Kotlin function. It’s a tiny difference, but it’s good to know it. Anyways, I hope you were able to understand the difference between these two functions. As mentioned in the article, if you want to get an in-depth understanding of what derivedStateOf is and when it should and shouldn’t be used, check out this article. Thank you for reading 😊. Happy coding 👨‍💻!

If you really liked my article and want to support me, you can do so, by clicking this link. Thank you so much for being generous ❤️, it really motivates me to keep going, and it helps me to keep my articles free for anyone to read. If you don’t feel like supporting, that’s fine too! The fact that you took some time off your schedule to read my article means a lot to me. Thank you 🙂

--

--

The Android Developer

| A very passionate Android Developer 💚 | An extreme Kotlin fanatic 💜 | A huge fan of Jetpack Compose 💙| Focused on making quality blog posts 📝 |