My navigation graph is a nested graph for an authe...
# compose
j
My navigation graph is a nested graph for an authentication flow. Once authenticated, I want to navigate to a screen with a bottom navigation bar, and my current implementation is to use a 2nd navigation controller for this bottom nav bar. Is it possible to do away with the 2nd navigation controller and use the 1st?
If i try to pass in the first nav controller instead of making a new one, I receive this error
c
Android team will recommend going this route in all likelyhood

https://youtu.be/09qjn706ITA?t=285

j
Copy code
java.lang.IllegalStateException: ViewModelStore should be set before setGraph call
c
The timestamp of that video, 4:45 shows ~"casestudy on login"
i
Here's the last discussion on hiding your bottom nav on certain destinations: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1620004053320700?thread_ts=1620002834.320600&cid=CJLTWPH7S
j
Definitely didn't think about conditionally hiding the bottom nav, and I like it. I know doing this conditionally would save me a lot of work, but I thought the additional documentation said nested nav graphs would be preferable for an auth flow?
👍 1
i
A nested Navigation graph means a
navigation
element within your graph's DSL
That's entirely different from a nested
NavHost
which is almost never the right approach
j
Yes, my current implementation is a
navigation
element, but it uses 2 nav controller, which I believe is unnecessary. Doing it conditionally would definitely solve my issue, so I guess what my question now is, when should I use a nav graph?
*er, I use 2 nav controller, 1 for the auth flow and then 1 for the bottom nav bar
One NavController, one NavHost, and a graph that is made up of one or more nested graphs
j
Yes, my nested nav graph is set up like the code example. It's just that, wouldn't I need a 2nd navhost to allow for the bottom nav bar? The 2nd navhost wouldn't be in the
NestedNavInGraph()
composable but would instead be inside a different composable like
Profile
or
Dashboard
composables in the sample code
i
No, you should not be using a second NavHost. All one graph, the bottom nav would be in the Scaffold outside the NavHost
👍 2
j
Alright, thank you for the clarification, and I apologize for the redundant questions. Have a good evening!
n
I did this recently and found it a little tricky to get the current destination when deep links were involved, but settled on the following code to detect the changes:
Copy code
val navBackStackEntry by nav.currentBackStackEntryAsState()

            LaunchedEffect(navBackStackEntry) {
                navBackStackEntry?.destination!!.arguments[KEY_ROUTE]?.defaultValue.toString()
                    .let { currentRoute ->
                        viewModel.onNavigationRouteChanged(currentRoute)
                    }
            }
You, obviously can ignore the viewModel stuff if it doesn't suit your architecture.
Then did:
Copy code
AnimatedVisibility(
                                        visible = showBottomNavigation,
                                        enter = slideInVertically(initialOffsetY = { it }),
                                        exit = slideOutVertically(targetOffsetY = { it })
                                    ) {
                                        MainBottomNavigation(nav)
                                    }
🙌 1
j
Ah thank you so much! I will definitely use this
i
Keep in mind that things like
LaunchedEffect
will run a frame behind, which might not be the best for animation purposes. Directly using the state as the source of truth (and using tools like
derivedStateOf
for computed state) is generally a much better reactive pattern
🙏 1
n
So, an improvement, as suggested by Ian might be this. I'd really love the API for
navBackStackEntry
to have some form of
getRouteOrNull
but otherwise, this isn't too bad. I still need to test whether this solves all cases for us, but so far, it seems to be working for most.
i
In this next release of Navigation, you'll just be able to do
navBackStackEntry?.destination?.route
👍 3