https://kotlinlang.org logo
#compose
Title
# compose
c

chanjungskim

03/07/2023, 3:51 AM
How can I call child composable function in parent composable function?
I'd like to initialize
value
when onClear is called.
Copy code
@Composable
fun NumberTypeQuestionLayout(
    min: Int,
    max: Int,
    hint: String,
    onClear: () -> Unit,
    onAnswer: (HashMap<String, String>) -> Unit,
    modifier: Modifier = Modifier
) {
    // FIXME
    var value by rememberSaveable { mutableStateOf("") }
}
Is there anything something similar to listener in compose?
p

Pablichjenkov

03/07/2023, 4:12 AM
Not sure if I understand your problem correctly but what I do to establish communication between parent and children is passing a state property from parent to children. Children then will interact with that given state, which allows the parent to listen for children events and send back results if any. Like an In/Out socket that the parent passes down
c

chanjungskim

03/07/2023, 4:19 AM
I am sorry, can I ask you how I can interact each other?
p

Pablichjenkov

03/07/2023, 4:42 AM
Something like below pseudo code
Copy code
class ParentState {

   val childStates: List<ChildState> = …
 …
   val callbackForChildren: Callback 
…

   interface Callback {
        fun childRequestSomething(childId: Int)
   }

}

Composable
fun Parent(parentState: ParentState) {
…
       for (i in 0 .. 10) {
               Child(parentState.childStates[i], parentState.callbackForChildren)
        }
…
}

Composable
fun Child(childState: ChildState, parentCallback: ParentState.ChildCallback) {
…
    onClick {
        parentCallback.childRequestSomething(childState.ID)
    }
…
}
The parent passes a State to each child but also passes a callback. That way if a child wants to reach the parent uses the callback. If the parent wants to reach the child, it then modifies the child state directly. For that, the parent needs to host the children state.
It could be designed in many ways, perhaps is better to place a callback inside each child state, that way you don’t need an ID to identify the child calling the parent, just handle each callback instance separately.
c

chanjungskim

03/07/2023, 4:48 AM
Okay, Thank you. I will try it. Or is there way to force initialize NumberTypeQuestionLayout when any value of the param is different from previous one?
@Pablichjenkov I checked the code you suggested, but in my case, it's not calling from child but calling from parent and change child's value. So,
Copy code
@Composable
fun Child(
    childData: ChildData,
    childState: ChildState,
    parentCallback: ParentState.ChildCallback
) {
   var value by rememberSaveable { mutableStateOf("") }
   // TODO: update value to "" with parentCallback
}
It will be something like this:
Copy code
@Composable
fun Parent(
    parentData: ParentData
){
    val parentState: ParentState

    Row{
        Child(childData, childState, parentCallback)
        Button(
            onClick = {
                parentState.fetchNextQuestion()
            }
        ){
            Text(text="next")
        }
    }
}
p

Pablichjenkov

03/07/2023, 6:09 AM
I see this suspicious:
Copy code
var value by rememberSaveable { mutableStateOf("") }
Could you use a key in rememberSaveable.
I am not to familiar with rememberSaveable but it might keep the previous composition LayoutNode State if not used with a Key, similar to remember. In any case, it should work.
fetchNextQuestion()
should mutate some State in the parent State that triggers recomposition, in which you pass the new state to the children. I am running out of time now but I might do a little example latter, kind of intrigue me.
605 Views