What is derivedStateOf and when is it useful?
Use derived state when Compose state changes more often than the UI actually needs to react.
What the interviewer is testing
The interviewer is usually testing whether you understand the difference between state changing and the UI actually needing to change because of it.
Compose state can change frequently, especially with things like scrolling. That is not automatically a problem, and recomposition is a normal part of Compose. The useful judgement is noticing when the UI only cares about a much simpler result than all of those individual state changes.
A strong answer explains why derivedStateOf can help in that situation, but also knows when to leave the code alone. If every input change should produce a new value on screen, a normal Kotlin expression is often the clearer choice.
❌ Common mistake
If they ask you to elaborate
Imagine a product list built with LazyColumn and a Back to top button.
A LazyColumn can keep its scroll information in a LazyListState, created with rememberLazyListState(). One of the values it exposes is firstVisibleItemIndex — simply the position of the first item currently visible on screen.
So as the user scrolls, that value might look like this:
first visible item
0 → 1 → 2 → 3 → 4 → 5 → 6 ...The button does not need all of those positions. It only needs to answer one question: has the user moved past the first item?
show button?
false → trueOnce the user is past the first item, changing from item 2 to 3, or 20 to 21, does not change what the button should display.
That is a good fit for derivedStateOf:
val listState = rememberLazyListState()
val showBackToTop by remember {
derivedStateOf {
listState.firstVisibleItemIndex > 0
}
}Now the UI can depend on showBackToTop instead of reacting to every visible-item change:
AnimatedVisibility(visible = showBackToTop) {
ScrollToTopButton()
}The useful part is not that Compose has calculated a Boolean. Kotlin could already do that.
The useful part is that the Boolean changes much less often than the scroll state it comes from.
When the list moves from item 4 to 5, Compose can check the derived value and see that it is still true. The UI reading showBackToTop does not need to react as though its state changed.
It is also worth separating this from remember.
Suppose sorting a list is expensive:
val sortedUsers = remember(users) {
users.sortedBy { it.name }
}Here remember(users) avoids doing the sort again while users has not changed.
That is a different problem.
With derivedStateOf, the interesting part is that the source can change many times while the value the UI cares about stays the same.
So a useful way to think about the two is:
Avoid repeating a calculation while its input is unchanged
→ remember(key)
Let source state change frequently,
but only update the UI when the derived result changes
→ derivedStateOfThere is another nearby API that solves a different problem.
If the screen should render a value such as showBackToTop, derivedStateOf is a natural fit.
If instead the app needs to react outside normal rendering — for example, send analytics the first time the user scrolls past the first item — that is closer to snapshotFlow, which can turn Compose state changes into a Flow.
That distinction keeps derivedStateOf focused on what it is good at: giving the UI a smaller piece of state to observe.
Production thinking
In production code, derivedStateOf is most useful when there is an obvious gap between how often something changes and how often the UI should change because of it.
Scrolling is the classic example because the difference is easy to see.
Imagine a product screen where the toolbar becomes compact after the user scrolls past 200 pixels:
val showCompactToolbar by remember {
derivedStateOf {
scrollState.value > 200
}
}scrollState.value may change on almost every small movement of the user's finger:
184 → 189 → 195 → 201 → 207 → 214 → 220 ...The toolbar does not care about all of those numbers. It only cares when the answer changes between:
false ↔ trueThat is the kind of code where derivedStateOf makes the relationship clearer and can avoid making the UI react to every intermediate scroll value.
Now compare it with a checkout screen:
val canCheckout =
cart.isNotEmpty() && selectedAddress != nullIf the cart changes or the selected address changes, the checkout button probably does need the new answer. There is no useful gap between the source changing and the UI needing to react.
Wrapping that in derivedStateOf would make the code look more sophisticated without solving a real problem.
That is why I would not treat derivedStateOf as a default performance trick. Start with ordinary Kotlin and normal Compose state. If profiling or the shape of the state makes it clear that a fast-changing value is causing UI work even though the meaningful result rarely changes, then derivedStateOf becomes a good tool.
The same rule helps during code review.
When this appears:
val something by remember {
derivedStateOf {
// ...
}
}the useful question is not:
"Is this derived from state?"
It is:
"Does this result change less often than the state it reads?"
If the answer is no, there is usually no reason for derivedStateOf to be there.
Follow-up questions
What separates a senior answer
Key takeaways
Learn more
When should data loading happen in LaunchedEffect versus ViewModel.init?
Decide what should trigger initial screen loading without confusing Composition lifetime with state ownership.
What is snapshotFlow?
Observe Compose-owned state as a Flow when work needs to react to changes instead of rendering them directly.