5

We have the official docs showcasing an example of backwards write in Compose:

@Composable
fun BadComposable() {
   var count by remember { mutableStateOf(0) }

   // Causes recomposition on click
    Button(onClick = { count++ }, Modifier.wrapContentSize()) {
        Text("Recompose")
   }
   Text("$count")
   count++ // Backwards write, writing to state after it has been read
}

It's clear to me that updating State object inside a composable like that causes a backwards write. The stated effect of this backwards write is that we end up with an infinite cycle of recompositions.

However, what's interesting is that the count++ increment action at the bottom of the composable doesn't trigger an infinite cycle of recompositions. Basically, on the first composition of BadComposable, everything seems fine as there are no extra recompositions even though we've updated count at the end of the body of BadComposable.

If, however, you then press on the Button, the count++ increment action inside the onClick callback triggers an infinite cycle of recompositions.

Why do we have to press on the Button to trigger an infinite cycle of recompositions? I was expecting that it's enough to read a value and update it in the body of the composable to get such an effect.

Jorge Castillo (thank you for your help) has hinted that it may be because the first update of the count state object happens before the initial recomposition scope of BadComposable is registered. Source for this idea.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Catalin Ghita
  • 794
  • 8
  • 26
  • Just wondering: did you test out that this actually behaves as stated? – Uli Jun 09 '22 at 13:58
  • 2
    Yes. You can attach the debugger on this sample and you will see that the infinite recompositions appear only after pressing on the button. – Catalin Ghita Jun 09 '22 at 17:37
  • If you wrap the increment in `SideEffect { count++ }` , do you end up in infinite recomposition? As you have it right now the composable hasn't finished the execution the first part, but if you wrap it in side effect that will executed after actual first composition being finished. – Nikola Despotoski Jun 14 '22 at 09:46
  • @NikolaDespotoski Yes. with `SideEffect`, `onClick` is not needed to trigger infinite recomposition – theapache64 Dec 27 '22 at 04:55

0 Answers0