Home > Enterprise >  Using Jetpack Compose State delegate syntax with data class
Using Jetpack Compose State delegate syntax with data class

Time:11-03

I really like using the by delegate with Compose State as it hides the boiler plate of having "reactive" data ie:

val message: String by remember { mutableStateOf("") }

message = "No boilerplate"

When using props this way, unidirectional data flow (or props down, events up) is clean and easy.

However when wanting to group data together in a data class, or observe a view model prop as state (ie: using observeAsAState()) I have to declare the prop of type State eg:

data class MyUiProps(
  val message: State<String>
)

var props = MyUiProps(viewModel.message.observesAsState(""))
props = MyUiProps(remember { mutableStateOf("") })

props.message.value = "Urgh boilerplate"

Is there a way to still use the by delegate with a data class like the following pseudo code

data class MyUiProps(
  val message: String
)

val props = MyUiProps(
  message = by remember { mutableStateOf("") }
)

props.message = "Yay no bolierplate"

CodePudding user response:

Just use MyUiProps as the state you are exposing in ViewModel. Exposing single fields is tedious and unreadable.

If you have something like this in ViewModel:

// Expose whole state in ViewModel
private val _state = MutableStateFlow(MyUiProps()) // this will set default values in the model
val state: StateFlow<MyUiProps> = _state // observe this as state in compose

// inside ViewModel if you want to update the state
_state.value = _state.value.copy(fieldYouWantToUpdate = newValue)

// in composable
val state by viewModel.state.collectAsState()

CodePudding user response:

You cannot use by inside a constructor. Still, you don't need the so-called "boilerplate" that you are showing. This is how you do it:

data class MyUiProps(
    var message: MutableState<String>
) {

}

val props = MyUiProps(
    message = remember { mutableStateOf("") }
)

props.message.value = "Yay no bolierplate"

You need to be using MutableState and not just State in your data classes parameter. This avoids the need to use observeAsState

  • Related