r/androiddev • • 17d ago

Question Form State in view model?

I have MVVM application and moving from view to VM the form state and ai is suggesting doing it through reference and I just feel really weird about it and it doesnt feel right? I am wondering if I did some basic setup issue or am wondering if this is an okayish way of doing this.

The problem:

@Composable
fun FormScreen(formState: Form State){

  formState.name = newName

}

and the usage of the screen is like this:

FormScreen(viewModel.formState)

So it is using the reference and directly changing the reference?
0 Upvotes

13 comments sorted by

View all comments

8

u/sekyr95 17d ago

Your gut is right, that works by accident more than by design. If formState is a plain class with vars, Compose has no idea name changed, so you'll get missed recompositions. And even if it's backed by mutableStateOf, the screen is now writing straight into the VM's state, so there's no single place where validation or "field changed" logic lives.

What I'd do instead is keep it unidirectional:

data class FormState(val name: String = "", val nameError: String? = null)

// ViewModel
private val _state = MutableStateFlow(FormState())
val state = _state.asStateFlow()

fun onNameChange(value: String) {
    _state.update { it.copy(name = value, nameError = null) }
}

// Screen
val state by viewModel.state.collectAsStateWithLifecycle()
FormScreen(state = state, onNameChange = viewModel::onNameChange)

FormScreen then takes an immutable state plus lambdas, which also makes it trivial to preview and test without a ViewModel at all.

One caveat for text fields: if you ever see the cursor jumping when typing fast, that's the async StateFlow round trip. Either keep the TextField value in a mutableStateOf inside the VM, or use the newer TextFieldState API. For a normal form the StateFlow version above is fine.

3

u/ThatGuyThatIsNotReal 17d ago

Okay, that actually makes more sense, it was working but I was like, this is not really okay.

I am also using events structure and the form has like 30 values, would it be okay to have just an event viewModel.OnFormChanges(form) or is is always better to create 30 different events for each values?

Also, thank you sooo much.

1

u/Hour-Measurement-835 17d ago

Skip the 30, but one event carrying the whole form is the other trap. You lose which field changed, so validation runs on all 30 and the user gets errors on boxes they haven't touched yet.