Hey, I have a question regarding recomposition sco...
# compose
k
Hey, I have a question regarding recomposition scopes, I am not sure if I understand them correctly - more in the thread đź§µ
I have a simple "screen" like this:
Copy code
@Composable
fun RecompositionScopeScreen() {
    var text by remember {
        mutableStateOf("A")
    }

    MyText(
        text = text,
        onClick = { text += "A" }
    )
}

@Composable
fun MyText(text: String, onClick: () -> Unit) {
    Text(modifier = Modifier.clickable { onClick() }, text = text, fontSize = 32.sp)
}
When I click the text, everything recomposes - RecompositionScopeScreen, MyText and Text. I thought only MyText would recompose - Is that because the text state is read in the MyText invocation:
Copy code
MyText(
        text = text,
        onClick = { text += "A" }
    )
? Making it recompose the RecompositonScopeScreen, because the state is read in its scope, MyText recomposes because of the parameter changes and so does Text. Or am I misunderstanding something? If i change the code to this:
Copy code
@Composable
fun RecompositionScopeScreen() {
    var text by remember {
        mutableStateOf("A")
    }

    MyText {
        Text(modifier = Modifier.clickable { text += "A" }, text = text, fontSize = 32.sp)
    }
}

@Composable
fun MyText(content: @Composable () -> Unit) {
    content()
}
Its only Text that recomposes. I assume its because it then only recomposes the content lambda scope as the state changes. Is that correct? Thanks!
z
Yes, if you do the state read in RecompositionScopeScreen directly, that function will recompose when the state changes.
gratitude thank you 1
k
Thank you Zach! May I also ask why this code with a deferred state read works too (the RecompositionScopeScreen doesnt recompose on text click, only MyText and Text within the MyText composable do)
Copy code
@Composable
fun RecompositionScopeScreen() {
    var text by remember {
        mutableStateOf("A")
    }

    MyText(
        text = { text },
        onClick = {
            text += "A"
        }
    )
}

@Composable
fun MyText(text: () -> String, onClick: () -> Unit) {
    Text(modifier = Modifier.clickable { onClick() }, text = text(), fontSize = 32.sp)
}
I've read the documentation but I can't still grasp why does using the lambda parameter change the behavior nono
z
It’s the same principle. It might be more apparent if you don’t use property delegation for the state object. The state read only occurs when the state object’s
value
property is read. Capturing a state object in a lambda is effectively like passing the state object itself to
MyText
. This capturing is not a state read, since it doesn’t involve calling
.value
.
gratitude thank you 1
It’s the same principle because in your second snippet, you’re passing a lambda to
MyText
as well, and that lambda is capturing the state object but not reading its
value
property.
gratitude thank you 1
k
Oh, i see... Thanks!