is there any way to change two different state at ...
# compose
z
is there any way to change two different state at the same time without recomposing?
a
withMutableSnapshot
will let you commit several snapshot state changes atomically and compose will see it as a single change. In some cases it's redundant or overkill though, what's your use case?
👍 2
z
I am using
ModalBottomSheetLayout
and I have to show different
BottomSheet
based on user action. Now if i change the
bottomSheetState
first then I can’t get the updated other state inside the
sheetBlock
Copy code
sealed class StudentEditSheet{
    object Email: StudentEditSheet()
    object Gender: StudentEditSheet()
    object Department: StudentEditSheet()
    object Level: StudentEditSheet()
    object Term: StudentEditSheet()
    object None: StudentEditSheet()
}

@ExperimentalComposeApi
@OptIn(ExperimentalMaterialApi::class)
@Composable
fun StudentEditScreen(
    viewModel: StudentEditViewModel,
    onBackPress: (() -> Unit)?,
    onNavigateToHome: () -> Unit
) {
    val sheetState = rememberModalBottomSheetState(ModalBottomSheetValue.Hidden)
    var studentEditSheet by remember { mutableStateOf<StudentEditSheet>(StudentEditSheet.None) }

    ModalBottomSheetLayout(
        sheetState = sheetState,
        sheetContent = {
            when (studentEditSheet) {
                StudentEditSheet.Gender -> {
                    ListBottomSheet(
                        title = stringResource(id = R.string.select_your_department),
                        icon = Icons.Outlined.DepartureBoard,
                        onClose = { studentEditSheet = StudentEditSheet.None },
                        list = (0..9).toList(),
                        onItemClick = { }
                    )
                }

                else -> {
                    Box(modifier = Modifier.size(100.dp))
                }
            }
        }
    ) {
        StudentEditScreenContent(
            stateFlow = viewModel.state,
            onFullNameChange = viewModel::changeFullName,
            onDiuIdChange = viewModel::changeDiuId,
            selectGender = {
                withMutableSnapshot {
                    sheetState.show()
                    studentEditSheet = StudentEditSheet.Gender
                }
            },
            onEmailClick = { studentEditSheet = StudentEditSheet.Email },
            onPhoneChange = viewModel::changePhoneNumber,
            selectDepartment = { studentEditSheet = StudentEditSheet.Department },
            selectLevel = { studentEditSheet = StudentEditSheet.Level },
            selectTerm = { studentEditSheet = StudentEditSheet.Term },
            changeImage = {},
            saveStudentProfile = viewModel::saveProfile,
            onBackPress = onBackPress
        )
    }
}
I think I am doing it wrong….
a
I'd have to give it a closer look than I can spare tonight to see what exactly is amiss, but I doubt it has to do with snapshot atomicity. Compose user input events all dispatch on the android main thread and compose will coalesce updates no more often than every
Choreographer
frame synced to the device's vsync interval; if you make two changes in the same event handler it's basically as good as putting it inside a
withMutableSnapshot
block anyway
(since
Choreographer
work also happens on the same thread as the event callbacks; they cannot run concurrently)
z
i have also tried reorganizing the state changes.
Copy code
studentEditSheet = StudentEditSheet.Gender
sheetState.show()
but I have the same effect. It ignores the first tap.
a
hmm, can you file an issue on the bug tracker and we'll take a look after the holidays? If you have an isolated repro it seems worth looking into
z
ok. I will file a but with an isolated repro.
👍 2
j
@zoha131 can you please link the issue you filed? thanks
z
i didn’t file any issue. I was unable to reproduce this in a fresh project. But somehow it is not working in my project.