Search code examples
androidkotlinandroid-jetpack-composecomposablecompose-recomposition

How to trigger recomposition when modify the parent data using CompositionLocal


when I use CompositionLocal, I have got the data from the parent and modify it, but I found it would not trigger the child recomposition.

I have successfully change the data, which can be proved through that when I add an extra state in the child composable then change it to trigger recomposition I can get the new data.

Is anybody can give me help?

Append

code like below


data class GlobalState(var count: Int = 0)

val LocalAppState = compositionLocalOf { GlobalState() }

@Composable
fun App() {
    CompositionLocalProvider(LocalAppState provides GlobalState()) {
        CountPage(globalState = LocalAppState.current)
    }
}

@Composable
fun CountPage(globalState: GlobalState) {
    // use it request recomposition worked
//    val recomposeScope = currentRecomposeScope
    BoxWithConstraints(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxSize()
            .clickable {
                globalState.count++
//                recomposeScope.invalidate()

            }) {
        Text("count ${globalState.count}")
    }
}

I found a workaround is using currentRecomposable to force recomposition, maybe there is a better way and pls tell me.


Solution

  • I am not sure why you are using compositionLocalOf in this way.

    Using the State hoisting pattern you can use two parameters in to the composable:

    • value: T: the current value to display.
    • onValueChange: (T) -> Unit: an event that requests the value to change where T is the proposed new value.

    In your case:

    data class GlobalState(var count: Int = 0)
    
    @Composable
    fun App() {
    
        var counter by remember { mutableStateOf(GlobalState(0)) }
        CountPage(
            globalState = counter,
            onUpdateCount = {
                    counter = counter.copy(count = counter.count +1)
                }
            )
    }
    
    @Composable
    fun CountPage(globalState: GlobalState, onUpdateCount: () -> Unit) {
       
        BoxWithConstraints(
            contentAlignment = Alignment.Center,
            modifier = Modifier
                .fillMaxSize()
                .clickable (
                    onClick = onUpdateCount
                )) {
            Text("count ${globalState.count}")
        }
    }