aster.cloud aster.cloud
  • /
  • Platforms
    • Public Cloud
    • On-Premise
    • Hybrid Cloud
    • Data
  • Architecture
    • Design
    • Solutions
    • Enterprise
  • Engineering
    • Automation
    • Software Engineering
    • Project Management
    • DevOps
  • Programming
    • Learning
  • Tools
  • About
  • /
  • Platforms
    • Public Cloud
    • On-Premise
    • Hybrid Cloud
    • Data
  • Architecture
    • Design
    • Solutions
    • Enterprise
  • Engineering
    • Automation
    • Software Engineering
    • Project Management
    • DevOps
  • Programming
    • Learning
  • Tools
  • About
aster.cloud aster.cloud
  • /
  • Platforms
    • Public Cloud
    • On-Premise
    • Hybrid Cloud
    • Data
  • Architecture
    • Design
    • Solutions
    • Enterprise
  • Engineering
    • Automation
    • Software Engineering
    • Project Management
    • DevOps
  • Programming
    • Learning
  • Tools
  • About
  • Programming

Jetpack Compose — When Should I Use DerivedStateOf?

  • aster.cloud
  • December 1, 2022
  • 5 minute read

derivedStateOf — a really common question we see is where and when is the correct place to use this API?

The answer to this question is <strong class="ki jk">derivedStateOf {}</strong> should be used when your state or key is changing more than you want to update your UI. Or in other words, derivedStateOf is like distinctUntilChanged from Kotlin Flows or other similar reactive frameworks. Remember that Composables recompose when the Compose state object they read, changes. derivedStateOf allows you to create a new state object that changes only as much as you need.


Partner with aster.cloud
for your next big idea.
Let us know here.



From our partners:

CITI.IO :: Business. Institutions. Society. Global Political Economy.
CYBERPOGO.COM :: For the Arts, Sciences, and Technology.
DADAHACKS.COM :: Parenting For The Rest Of Us.
ZEDISTA.COM :: Entertainment. Sports. Culture. Escape.
TAKUMAKU.COM :: For The Hearth And Home.
ASTER.CLOUD :: From The Cloud And Beyond.
LIWAIWAI.COM :: Intelligence, Inside and Outside.
GLOBALCLOUDPLATFORMS.COM :: For The World's Computing Needs.
FIREGULAMAN.COM :: For The Fire In The Belly Of The Coder.
ASTERCASTER.COM :: Supra Astra. Beyond The Stars.
BARTDAY.COM :: Prosperity For Everyone.

Let’s take a look at an example. Here we have a username field and a button that enables when the username is valid.

/* Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0 */

var username by remember { mutableStateOf("") }
val submitEnabled = isUsernameValid(username)
Initial state of username and submitEnabled

It starts off empty and so our state is false. Now when the user starts typing, our state correctly updates and our button becomes enabled.

But here is the problem, as our user keeps typing we are sending state to our button over and over again needlessly.

State updates after the user continues typing

This is where derivedStateOf comes in. Our state is changing more than we need our UI to update and so derivedStateOf can be used for this to reduce the number of recompositions.

/* Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0 */

var username by remember { mutableStateOf("") }
val submitEnabled = remember {
  derivedStateOf { isUsernameValid(username) }
}
Updating the code to use derivedStateOf

Let’s go through the same example again to see the difference.

State updates with derivedStateOf

The user starts typing, but this time our username state is the only one that changes. The submit state just remains true. And of course, if our username becomes invalid. Our derived state correctly updates again.

Now, this example is a bit oversimplified. In a real app, Compose would most likely skip recomposition of the submit composable as its input parameters have not changed.

Read More  How To Get Started With Klaviyo - A Developer's Guide

The reality is, the situations when you need derivedStateOf can feel few and far between. But when you do find a case, it can be supremely effective at minimizing recomposition.

Always remember that there needs to be a difference in the amount of change between the input arguments and output result for <strong class="ki jk">derivedStateOf</strong> to make sense.

Some examples of when it could be used (not exhaustive):

  • Observing if scrolling passes a threshold (scrollPosition > 0)
  • Items in a list is greater than a threshold (items > 0)
  • Form validation as above (username.isValid())

FAQs

Now, let’s look at some other commonly asked questions about derivedStateOf.

Does derivedStateOf have to be remembered?

If it is inside a Composable function, yes. derivedStateOf is just like <a class="au li" href="https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#mutableStateOf(kotlin.Any,androidx.compose.runtime.SnapshotMutationPolicy)" target="_blank" rel="noopener ugc nofollow">mutableStateOf</a> or any other object that needs to survive recomposition. If you use it inside a composable function then it should be wrapped in a <a class="au li" href="https://developer.android.com/reference/kotlin/androidx/compose/runtime/package-summary#remember(kotlin.Any,kotlin.Any,kotlin.Any,kotlin.Function0)" target="_blank" rel="noopener ugc nofollow">remember</a> or else it will be reallocated on every recomposition.

/* Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0 */

@Composable
fun MyComp() {
  // We need to use remember here to survive recomposition
  val state = remember { derivedStateOf { … } }
}

class MyViewModel: ViewModel() {
  // We don't need remember here (nor could we use it) because the ViewModel is
  // outside of Composition.
  val state = derivedStateOf { … }
}

What’s the difference between remember(key) and derivedStateOf?

Remember with keys of each state and derivedStateOf can seem quite similar at first glance.

/* Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0 */

val result = remember(state1, state2) { calculation(state1, state2) }
val result = remember { derivedStateOf { calculation(state1, state2) } }

The difference between remember(key) and derivedStateOf is in the amount of recomposition. <strong class="ki jk">derivedStateOf {}</strong> is used when your state or key is changing more than you want to update your UI.

Read More  Android Studio Bumblebee (2021.1.1) Stable

Take for example enabling a button only if the user has scrolled a LazyColumn.

val isEnabled = lazyListState.firstVisibileItemIndex > 0

firstVisibleItemIndex will change 0, 1, 2 etc as the user scrolls and causes readers to recompose every time it changes. We only care about if it’s greater than 0 or not. There is a difference in the amount of input we have and output we need and so derivedStateOf is used here to buffer out that unnecessary recomposition.

val isEnabled = remember {
derivedStateOf { lazyListState.firstVisibleItemIndex > 0 }
}

Now, let’s say we have an expensive function that calculates something for us with a parameter. We want our UI to recompose any time the output of that function changes (importantly, the function is also idempotent). We use remember with a key here, as our UI needs to update just as much as our key changes. That is, we have the same amount of input and output.

val output = remember(input) { expensiveCalculation(input) }

Do I ever need to use remember(key) and derivedStateOf together? When is this needed?

This is where things get a little tricky. derivedStateOf can only update when it reads a Compose state object. Any other variables read inside derivedStateOf will capture the initial value of that variable when the derived state is created. If you need to use those variables in your calculation, then you can provide them as a key to your remember function. This concept is much easier to understand with an example. Let’s take our isEnabled example from before and expand it to also have a threshold for when to enable the button, rather than 0.

Read More  Google I/O 2019 | What’s New in ARCore
/* Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0 */

@Composable
fun ScrollToTopButton(lazyListState: LazyListState, threshold: Int) {
  // There is a bug here
  val isEnabled by remember {
    derivedStateOf { lazyListState.firstVisibleItemIndex > threshold }
  }
  
  Button(onClick = { }, enabled = isEnabled) {
    Text("Scroll to top")
  }
}

Here we have a button that enables when a list is scrolled over a threshold. We are correctly using derivedStateOf to remove the extra recomposition, but there is a subtle bug. If the threshold parameter changes, our derivedStateOf won’t take the new value into account as it captures the initial value on creation for any variable that isn’t a compose state object. As threshold is an Int, whatever is the first value that is passed into our composable will be captured and used for the calculation from then on. ScrollToTopButton will still recompose, as its inputs have changed, but as remember without any keys caches across recomposition, it will not reinitialise the derivedStateOf with the new value.

We can see this by looking at the outputs from our code. At first everything is working correctly.

But then a new value (5) for threshold is passed into our composable.

Even though our scrollPosition is less than threshold, isEnabled is still set to true.

The fix here is to add threshold as a key for remember, this will reinitialise our derivedStateOf state anytime threshold changes.

/* Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0 */

val isEnabled by remember(threshold) {
  derivedStateOf { lazyListState.firstVisibleItemIndex > threshold }
}

Now we can see, when the threshold changes, the isEnabled state correctly updates.

Do I need to use derivedStateOf to combine multiple states together?

Most likely, no. If you have multiple states that are combining together to create a result then you probably want recomposition to happen any time one of them changes.

Take for example a form that takes in a first name and last name and displays a full name.

/* Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0 */

var firstName by remember { mutableStateOf("") }
var lastName by remember { mutableStateOf("") }

val fullName = "$firstName $lastName"

Here, as our output changes just as much as our input, derivedStateOf is not doing anything and is just causing a small overhead. derivedStateOf also isn’t helping with asynchronous updates, the Compose state snapshot system is dealing with that separately and these calls here are synchronous.

In this case, there is no need for an extra derived state object at all.

/* Copyright 2022 Google LLC.
SPDX-License-Identifier: Apache-2.0 */

var firstName by remember { mutableStateOf("") }
var lastName by remember { mutableStateOf("") }

val fullName = "$firstName $lastName"

Conclusion

To sum up, remember that derivedStateOf is used when your state or key is changing more than you want to update your UI. If you don’t have a difference in the amount of input compared with output, you don’t need to use it.

By Ben Trengrove
Source Android


For enquiries, product placements, sponsorships, and collaborations, connect with us at [email protected]. We'd love to hear from you!

Our humans need coffee too! Your support is highly appreciated, thank you!

aster.cloud

Related Topics
  • Android
  • API
  • derivedStateOf
  • Jetpack Compose
You May Also Like
View Post
  • Architecture
  • Data
  • Engineering
  • People
  • Programming
  • Software Engineering
  • Technology
  • Work & Jobs

Predictions: Top 25 Careers Likely In High Demand In The Future

  • June 6, 2023
View Post
  • Programming
  • Software Engineering
  • Technology

Build a Python App to Alert You When Asteroids Are Close to Earth

  • May 22, 2023
View Post
  • Programming

Illuminating Interactions: Visual State In Jetpack Compose

  • May 20, 2023
View Post
  • Computing
  • Data
  • Programming
  • Software
  • Software Engineering

The Top 10 Data Interchange Or Data Exchange Format Used Today

  • May 11, 2023
View Post
  • Architecture
  • Programming
  • Public Cloud

From Receipts To Riches: Save Money W/ Google Cloud & Supermarket Bills – Part 1

  • May 8, 2023
View Post
  • Programming
  • Public Cloud

3 New Ways To Authorize Users To Your Private Workloads On Cloud Run

  • May 4, 2023
View Post
  • Programming
  • Public Cloud

Buffer HTTP Requests With Cloud Tasks

  • May 4, 2023
View Post
  • Programming
  • Public Cloud
  • Software
  • Software Engineering

Learn About Google Cloud’s Updated Renderer For The Maps SDK For Android

  • May 4, 2023

Stay Connected!
LATEST
  • college-of-cardinals-2025 1
    The Definitive Who’s Who of the 2025 Papal Conclave
    • May 7, 2025
  • conclave-poster-black-smoke 2
    The World Is Revalidating Itself
    • May 6, 2025
  • 3
    Conclave: How A New Pope Is Chosen
    • April 25, 2025
  • Getting things done makes her feel amazing 4
    Nurturing Minds in the Digital Revolution
    • April 25, 2025
  • 5
    AI is automating our jobs – but values need to change if we are to be liberated by it
    • April 17, 2025
  • 6
    Canonical Releases Ubuntu 25.04 Plucky Puffin
    • April 17, 2025
  • 7
    United States Army Enterprise Cloud Management Agency Expands its Oracle Defense Cloud Services
    • April 15, 2025
  • 8
    Tokyo Electron and IBM Renew Collaboration for Advanced Semiconductor Technology
    • April 2, 2025
  • 9
    IBM Accelerates Momentum in the as a Service Space with Growing Portfolio of Tools Simplifying Infrastructure Management
    • March 27, 2025
  • 10
    Tariffs, Trump, and Other Things That Start With T – They’re Not The Problem, It’s How We Use Them
    • March 25, 2025
about
Hello World!

We are aster.cloud. We’re created by programmers for programmers.

Our site aims to provide guides, programming tips, reviews, and interesting materials for tech people and those who want to learn in general.

We would like to hear from you.

If you have any feedback, enquiries, or sponsorship request, kindly reach out to us at:

[email protected]
Most Popular
  • 1
    IBM contributes key open-source projects to Linux Foundation to advance AI community participation
    • March 22, 2025
  • 2
    Co-op mode: New partners driving the future of gaming with AI
    • March 22, 2025
  • 3
    Mitsubishi Motors Canada Launches AI-Powered “Intelligent Companion” to Transform the 2025 Outlander Buying Experience
    • March 10, 2025
  • PiPiPi 4
    The Unexpected Pi-Fect Deals This March 14
    • March 13, 2025
  • Nintendo Switch Deals on Amazon 5
    10 Physical Nintendo Switch Game Deals on MAR10 Day!
    • March 9, 2025
  • /
  • Technology
  • Tools
  • About
  • Contact Us

Input your search keywords and press Enter.