Skip to main content

useCached

useCached is a hook that, rather than have to repeatedly make an expensive calculation, enables a component to calculate and maintain a cached value. It is calculated when the component is first added to the ComponentTree, and only recalculated when any of the dependencies provided in the useCached declaration changes.

To familiarize yourself with the concept and rules for hooks, see the Introduction to Hooks page.

Example: Cached value with dependencies​

In the following code, useCached is used to create and maintain an expensive-to-calculate value, which can be used multiple times across renders without repeating the expensive calculation.

Since the useCached declaration defines a dependency, the value will be calculated when the component is attached to the ComponentTree, and then recalculated every time the dependency changes.

class UseCachedWithDependencyComponent : KComponent() {
override fun ComponentScope.render(): Component {
val number = useState { 1 }

val expensiveValue = useCached(number) { expensiveRepeatFunc("hello", number.value) }

return Column(style = Style.onClick { number.update { n -> n + 1 } }) {
child(Text(text = expensiveValue))
}
}

companion object {
private fun expensiveRepeatFunc(prefix: String, num: Int = 20): String {
return StringBuilder().apply { repeat(num) { append(prefix) } }.toString()
}
}
}

Example: Cached value without dependencies​

In the code below, since useCached does not declare a dependency, the value will be calculated only once when the component is attached to the ComponentTree but will not be recalculated when the state value changes. The initial value of the state will always be used.

note

It's a common mistake to use the state in useCached without defining it as a dependency then expect the cached value to be recalculated when the state is updated.

class UseCachedWithoutDependencyComponent : KComponent() {
override fun ComponentScope.render(): Component {
val number = useState { 1 }

val expensiveValue = useCached {
// state isn't declared as a dependency, so initial state value will always be used
expensiveRepeatFunc("hello", number.value)
}

return Column(style = Style.onClick { number.update { n -> n + 1 } }) {
child(Text(text = expensiveValue))
}
}