Home > front end >  Can we still use the variable delegate for variable pass through parameter?
Can we still use the variable delegate for variable pass through parameter?

Time:01-14

We have the below compose which works well.

@Composable
fun MyInnerControl() {
    var timerStartStop by remember { mutableStateOf(true) }
    Button(onClick = {
        timerStartStop = !timerStartStop
    }) {
        Text(if (timerStartStop) "Stop" else "Start")
    }
}

But if we have the timerStartStop passed through the function parameter, I cannot do as below

@Composable
fun MyInnerControl(timerStartStop: Boolean) {
    Button(onClick = {
        timerStartStop = !timerStartStop
    }) {
        Text(if (timerStartStop) "Stop" else "Start")
    }
}

I can pass as below, but then I have to change my timerStartStop to timerStartStop.value

@Composable
fun MyInnerControl(timerStartStop: MutableState<Boolean>) {
    Button(onClick = {
        timerStartStop.value = !timerStartStop.value
    }) {
        Text(if (timerStartStop.value) "Stop" else "Start")
    }
}

Is there any way to have the MutableState<Boolean> passed over the argument, yet within the function we can use the delegate approach, i.e. using timerStartStop instead of timerStartStop.value?

CodePudding user response:

Jetpack Compose tells you to respect Single Source of Truth principle, which means that you can not pass state as argument if you want to change that state inside your function.

So generally you have to choose one of two approaches:

  1. Pass both timerStartStop variable and onClick callback
@Composable
fun MyInnerControl(timerStartStop: Boolean, onClick: ()->Unit) {
    Button(onClick = onClick) {
        Text(if (timerStartStop) "Stop" else "Start")
    }
}
  1. Pass none of these
@Composable
fun MyInnerControl() {
    var timerStartStop by remember { mutableStateOf(true) }
    Button(onClick = {
        timerStartStop = !timerStartStop
    }) {
        Text(if (timerStartStop) "Stop" else "Start")
    }
}

CodePudding user response:

I think it's better to apply proper state hoisting methods and give MyInnerControl the ability to both read and edit the parameter in the following way.

@Composable
fun ParentComposable() {
  val isTimerRunning by remember { mutableStateOf(false) } }
  MyInnerControl(
    isTimerRunning = isTimerRunning,
    flipTimerState {
      isTimerRunning = !isTimerRunning
    }
  }
}

@Composable
fun MyInnerControl(
  isTimerRunning: Boolean,
  flipTimerState: () -> Unit,
) {
  Button(
    onClick = { flipTimerState() }
  ) {
    Text(if (isTimerRunning) "Stop" else "Start")
  }
}
  •  Tags:  
  • Related