derivedStateOf

derivedStateOf and remember with Keys

firstVisibleItemIndex changes with every row that scrolls past, but a "Back to top" label only cares whether it is above zero. ScrollDirect reads the test in its body; ScrollDerived wraps it in derivedStateOf, which invalidates readers only when the result changes:

StateDemos.kt: the flag through derivedStateOfKotlin
@Composable
fun ScrollDerived(books: List<Book>) {
  LogCompositions("ScrollDerived")
  val listState = rememberLazyListState()
  val showTop by remember { derivedStateOf { listState.firstVisibleItemIndex > 0 } }
  BookScroller(books, listState, showTop)
}

BookScroller builds 60 rows in remember(books, byPrice) { }, rerun only when a key changes, like useMemo. Three swipes on ScrollDerived, then Sort by price:

Output of 90
D/BookNestState: building rows byPrice=false
D/BookNestState: ScrollDerived composed #1
D/BookNestState: BookScroller composed #1
D/BookNestState: ScrollDerived composed #2
D/BookNestState: BookScroller composed #2
D/BookNestState: building rows byPrice=true
D/BookNestState: BookScroller composed #3

ScrollDerived recomposed once, when the flag flipped; ScrollDirect recomposed six times for the same swipes. The rows were rebuilt only when the byPrice key changed; without it, the stale order would stay.