key

Composable Function

Common
@Composable
public inline fun <T> key(
    @Suppress("UNUSED_PARAMETER") vararg keys: Any?,
    block: @Composable () -> T,
): T

key is a utility composable that is used to "group" or "key" a block of execution inside of a composition. This is sometimes needed for correctness inside of control-flow that may cause a given composable invocation to execute more than once during composition.

The value for a key does not need to be globally unique, and needs only be unique amongst the invocations of key at that point in composition.

For instance, consider the following example:

Even though there are users with the same id composed in both the top and the bottom loop, because they are different calls to key, there is no need to create compound keys.

The key must be unique for each element in the collection, however, or children and local state might be reused in unintended ways.

For instance, consider the following example:

This example assumes that parent.id is a unique key for each item in the collection, but this is only true if it is fair to assume that a parent will only ever have a single child, which may not be the case. Instead, it may be more correct to do the following:

A compound key can be created by passing in multiple arguments:

Parameters

keysThe set of values to be used to create a compound key. These will be compared to their previous values using equals and hashCode
blockThe composable children for this group.

Code Examples

LocallyUniqueKeys

@Composable
fun LocallyUniqueKeys() {
    for (user in users) {
        key(user.id) { UserPreview(user = user) }
    }
    for (user in users.filter { isAdmin }) {
        key(user.id) { Friend(friend = user) }
    }
}

NotAlwaysUniqueKeys

@Composable
fun NotAlwaysUniqueKeys() {
    for ((child, parent) in relationships) {
        key(parent.id) {
            User(user = child)
            User(user = parent)
        }
    }
}

MoreCorrectUniqueKeys

@Composable
fun MoreCorrectUniqueKeys() {
    for ((child, parent) in relationships) {
        key(parent.id to child.id) {
            User(user = child)
            User(user = parent)
        }
    }
}

TwoInputsKeySample

@Composable
fun TwoInputsKeySample() {
    for (element in elements) {
        val selected by key(element.id, parentId) { remember { mutableStateOf(false) } }
        ListItem(item = element, selected = selected)
    }
}