useCallback

fun <R> ComponentScope.useCallback(callback: () -> R): () -> R

useCallback allows a parent to pass a child component a callback which: 1) maintains referential equality across multiple layout passes 2) is updated to have the latest parent props and state, even if the child doesn't re-render.

Example

This sounds complicated, so it helps to step back a bit to provide context via example:

Say we have a parent component which renders a list of children via a Collection. Let's say we also want this parent to implement multi-select behavior, meaning on click, a row can be marked as selected/de-selected. We will store the state of which components are currently selected in the parent, and the parent will pass a lambda to the child to allow that state to be updated when a row is clicked.

When the first row is clicked, it will update the state in the parent via an onClick lambda. At this point, we ideally want to re-render only that row since that's the only row whose UI will be updated, i.e. to a selected state. However, that means the rest of the children will still have that original onClick lambda set on them: if that lambda captured props/state, then invoking it will operate on stale props/state! In this case, that means selecting a second row will de-select the first one which is incorrect.

An alternative is to always re-render all children whenever the list of selected items changes. This is effective in that it will make sure all children have a lambda capturing the latest props/state, however it's inefficient since it re-renders all children even though their UI doesn't appear different.

useCallback tries to give the best of both worlds: it doesn't cause children to re-render, and also gives a mechanism for them to invoke a lambda that has captured the latest props and state.

Notes: Thread Safety

The callback that will be invoked by the function returned by useCallback is updated when a new layout has been committed on the main thread. This means that useCallback should only be used with events that will also be invoked from the main thread, e.g. onClick.


fun <A, R> ComponentScope.useCallback(callback: (A) -> R): (A) -> R

1-parameter overload of useCallback: refer to docs there.


fun <A, B, R> ComponentScope.useCallback(callback: (A, B) -> R): (A, B) -> R

2-parameter overload of useCallback: refer to docs there.


fun <A, B, C, R> ComponentScope.useCallback(callback: (A, B, C) -> R): (A, B, C) -> R

3-parameter overload of useCallback: refer to docs there.


fun <A, B, C, D, R> ComponentScope.useCallback(callback: (A, B, C, D) -> R): (A, B, C, D) -> R

4-parameter overload of useCallback: refer to docs there.


fun <A, B, C, D, E, R> ComponentScope.useCallback(callback: (A, B, C, D, E) -> R): (A, B, C, D, E) -> R

5-parameter overload of useCallback: refer to docs there.


fun <A, B, C, D, E, F, R> ComponentScope.useCallback(callback: (A, B, C, D, E, F) -> R): (A, B, C, D, E, F) -> R

6-parameter overload of useCallback: refer to docs there.


fun <A, B, C, D, E, F, G, R> ComponentScope.useCallback(callback: (A, B, C, D, E, F, G) -> R): (A, B, C, D, E, F, G) -> R

7-parameter overload of useCallback: refer to docs there.