<@UHAJKUSTU> ```@Composable internal fun RootConte...
# decompose
s
@Arkadii Ivanov
Copy code
@Composable
internal fun RootContent(component: RootComponent) {
    Children(
        stack = component.childStack,
        animation = stackAnimation(fade()),
    ) {
        println("child stack =====  ${component.childStack.value}")
        when (val child = it.instance) {
            is RootComponent.Child.EnterMobileNumber -> LoginComponent(child.component)
            is RootComponent.Child.EnterOtp -> OtpComponent(child.component)
            is RootComponent.Child.ProjectListing -> ProjectListingMainScreen(child.component)
            is RootComponent.Child.ProjectDetails -> ProjectDetailsScreen(child.component)
            is RootComponent.Child.Notifications -> NotificationScreen(child.component)
            is RootComponent.Child.ImagePreviewFullScreen -> ImagePreviewFullScreen(child.component)
        }
    }
}
THis is my root content , after logging in i am on ProjectListing Child, how do i pop when i logout the user to move the stack to EnterMobileNumber. Stack EnterMobileNumber->EnterOtp->ProjectListing , on ProjectListing i press logout how do i pop stack? trying pop() but its not working correctly for this case.
j
You could use something like replaceAll or popTo(index) etc.
s
there is no such method popTo
you have to call it in you navigation property within your component
Copy code
class DefaultRootComponent(
    componentContext: ComponentContext
) : RootComponent, ComponentContext by componentContext {

    private val navigation = StackNavigation<Config>()
    ....
}
s
Copy code
2.0.0-compose-experimental-alpha-02"
using this version unable to access popTo
also tried this
Copy code
while (childStack.backStack.isNotEmpty()) {
    navigation.pop()
}
as i want to move to first component but is not working
@Jan got it it was issue with my states , pop is working fine.
@Jan can you tell me if i am navigating back how do i clear states in backstack components(having their own stores), before or immediately after navigating?
As the issue is when in am navigating back , the states in backstack component sends onOutput event and moves me forward
j
if your subcomponent has e.g. a logout button you have to pass a "logout"-callback during the creation of your subcomponent within you rootcomponent. Your subcomponent will then call the "logout"-callback via onclick which will be propagated it your rootcomponent. In your root component you can then clear your stackNavigation via pop, popTo, replaceAll, etc.
s
@Jan i am passing OnOutput event for logout action and handling in RootComponent. cant use callback for inter-component communication
a
The
popTo
method was introduced in version 2.0.0-beta-01. However, in your case you would be better using popWhile.
Copy code
navigation.popWhile { it !is Config.EnterMobileNumber }
But actually, it would be better to remove unneeded components from the stack, so they could be destroyed and resources released. E.g. after successful login you could just call
navigation.replaceAll(Config.ProjectListing(...)
. Then when you need to login again, you can call
navigation.replaceAll(Config.EnterMobileNumber(...))
.
s
@Arkadii Ivanov a simple and precise answer to my problem. thanks a lot . got it!
a
If you ever need different animations for push/pop and replaceAll cases (e.g. animate logged in/logged out transitions with
fade
, and push/pop with
slide
), then I suggest to decompose your root component by two. E.g. extract the login flow (the login related components) to a
LoginComponent
, and the rest into
MainComponent
. In this case you can utilize nested navigation, and have
Children
on the root level with
fade
animation, and
Children
on inner levels with
slide
.
s
@Arkadii Ivanov this is my root component is this correct or wrong approach?
Copy code
private sealed class Configuration : Parcelable {
    @Parcelize
    object EnterMobileNumber : Configuration()

    @Parcelize
    data class EnterOtp(var mobile: String, val verificationId: String) : Configuration()

    @Parcelize
    object ProjectListing : Configuration()

    @Parcelize
    data class ProjectDetails(val projectId: String) : Configuration()

    @Parcelize
    data class ImagePreviewFullScreen(
        val imagesList: List<PreviewFile>, val initialImageIndex: Int = 0
    ) : Configuration()
}
a
This is technically correct. However as your root component grows, or you want different animations when you navigate from Listing to Details or replace with EnterMobileNumber, it could be beneficial to decompose the root by two sub-components. One would contain EnterMobileNumber and EnterOtp, and the other one all the rest. Feel free to do it later when needed, to avoid premature optimizations.
s
thanks, one last question EnterMobileNumber->EnterOtp when on EnterOtp and i press back button , onOutput i do pop(), so lands on EnterMobileNumber, but becauses states are set in EnterMobileNumberStore, it agains sends me to EnterOtp how to handle this case, both have their own stores and storefactory
a
You could update the state once the navigation is performed. Or another option is to perform the navigation via Label.