Skip to content
AB

Predictable Compose Recomposition with State Hoisting

Control ownership, stability, derived values, and list identity before reaching for premature performance tricks.

Ashish BhakhandPublished

Recomposition is normal. The problem is expensive or incorrect work performed during it.

Hoist state to the lowest owner that coordinates every consumer. A reusable picker can own transient expanded state, while the selected value belongs to its parent or ViewModel.

Code
@Composable
fun MetricPicker(
    selected: Metric,
    onSelected: (Metric) -> Unit,
) { /* render only */ }

Avoid allocating repositories, formatters with heavy setup, or large transformed lists inside the composable body. Use remember for UI-local objects whose lifetime matches the composition, and derivedStateOf when an observed result changes less often than its inputs.

Lazy lists need stable item keys. Without them, insertion and reordering can move remembered row state to the wrong item.

Immutable models help Compose determine whether parameters changed. Stability annotations should describe reality, not silence tooling around mutable objects.

Measure with layout inspection and profiling before adding memoization everywhere. Often the real issue is reading broad state at the top of a large tree. Pass narrow values so only affected subtrees observe change.

State hoisting is first an ownership tool. Predictable performance follows because each value has one source and a limited observation scope.

← Back to all writing