State Hoisting

State hoisting moves state to the caller and replaces it with a value and an event callback, React 7,897 's controlled component: QuantityStepper(quantity: Int, onQuantityChange: (Int) -> Unit) owns nothing. State flows down, events flow up. The state goes to the lowest common parent of its readers; the cart total needs every quantity, so CartScreen owns them:

StateDemos.kt: the cart owns the state its children displayKotlin
@Composable
fun CartScreen(books: List<Book>) {
  LogCompositions("CartScreen")
  val quantities = remember { mutableStateMapOf<Int, Int>() }   // book id to quantity
  val total = books.sumOf { it.price * (quantities[it.id] ?: 0) }
  Column(Modifier.padding(20.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
    books.forEach { book ->
      CartLine(book, quantities[book.id] ?: 0, onQuantityChange = { quantities[book.id] = it })
    }
    Text("Total: $%.2f".format(total), style = MaterialTheme.typography.titleLarge)
  }
}

Hoist no higher than needed, because whoever reads a state recomposes; when logic grows, the owner becomes a ViewModel (ViewModel and UDF).