In my Jetpack Compose MVVM app, I have a parent sc...
# compose
p
In my Jetpack Compose MVVM app, I have a parent screen with a
NavHost
that navigates between several tabs. Each tab receives a shared
House
object (hoisted in the parent) to display and update its content. The problem: Each tab also has its own
ViewModel
and
UiState
with extra fields (like text fields, switches, filters) that are local to that tab. When I press a "Reset House" button in the last tab, I clear the shared
House
object in the parent ViewModel — and that works, the tabs see the empty
House
. But the local UI state in each tab's ViewModel (like text fields and switches) is not reset, so old values remain. Is there a good practice to reset both the shared object and all child ViewModels' UI states when pressing the reset button? Whould be a good option to navigate to first tab deleting the viewmodels of the childs from the backstack... but I tried it and doesn't happen that. The child tabs viewmodels still keeps the content
Copy code
// Parent NavHost
NavHost(navController, startDestination = "details") {
    composable("details") {
        HouseDetailsScreen(
            address = parentVm.uiState.house.address,
            onUpdateAddress = { parentVm.updateAddress(it) }
        )
    }
    composable("type") {
        HouseTypeScreen(
            selectedType = parentVm.uiState.house.type,
            onTypeSelected = { parentVm.updateType(it) }
        )
    }
    composable("review") {
        HouseReviewScreen(
            house = parentVm.uiState.house,
            onReset = {
                parentVm.resetHouse()
                navController.navigate("details") {
                    popUpTo(navController.graph.startDestinationId) { inclusive = true }
                }
                // TODO: also reset all child ViewModels' UI states
            }
        )
    }
}
Copy code
// Example child ViewModel
data class HouseTypeUiState(
    val loading: Boolean = false,
    val favoriteTypesOnly: Boolean = false
)

class HouseTypeViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(HouseTypeUiState())
    val uiState: StateFlow<HouseTypeUiState> = _uiState

    var searchQuery by mutableStateOf("")
        private set
}
Copy code
// Example child Composable
@Composable
fun HouseTypeScreen(
    selectedType: String?,
    vm: HouseTypeViewModel = koinViewModel(),
    onTypeSelected: (String) -> Unit
) {
    val uiState by vm.uiState.collectAsState()
    // ...
}
a
It would probably work to have a shared repository or use case that keeps the shared
House
and propagates changes in a Flow. That way you can clear the state in that shared place, and the flow should update the listening ViewModels.
☝️ 1
☝🏻 1