Dummy question… Do I have to pass my `navControlle...
# compose
n
Dummy question… Do I have to pass my
navController
to all my screens (of course if I want to navigate to somewhere else from that screen)? Should I create a
compositionLocalOf
for it?
n
Thanks @Abhishek Dewan 😉 I created a helper function based on your code:
Copy code
@Composable
fun withNavigator(navController: NavController, content: @Composable () -> Unit) {
    CompositionLocalProvider(LocalMainNavigator provides navController) {
        content()
    }
}
and use it like this:
Copy code
withNavigator(navController) {
    WelcomeScreen()
}
humm… if you wrap the
NavHost
with this function, it works think smart so don’t need to wrap all screens…
💯 1
f
The recommendation is to not pass the nav controller around and instead provide callbacks that will navigate to your destinations
i
Yep, the guide specifically suggests against passing your NavController down to any screen Composable: https://developer.android.com/jetpack/compose/navigation#testing
a
Interestingly I saw that guide and I tried doing what it suggested and I found that my code got messy. Since I like breaking my composable into smaller chunks, it meant passing the lambda down 3 / 4 levels of composable’s just to have a button trigger a navigation event. Is there a different pattern of breaking composable’s that can avoid the code looking messy?
i
every reusable composable should be taking state in and sending events out, that's true whether you're using Navigation or not. That's how you build Composables you can test in isolation and a natural part of Compose code
💯 2
a
This is indeed helpful ! I guess since I’ve not tried my hand at writing tests for the composable’s I’ve been building (still learning) I haven’t run into issues with this approach (which I am sure I will) It would interesting for me to take my project and move it away from using `compositionLocalOf`for the navigation code and see how it goes. Perhaps I can report back to this thread when I’ve done so 🙂
n
Thanks @Ian Lake 👍
i
The same testing story also applies to previews, which is definitely recommend taking heavy advantage of to iterate quickly
n
Another question: I’m defining the “back button” on the
TopAppBar
. Once I’m not passing the
navController
to my screens, should I pass a callback to pop current the screen?
f
do your screen explicitly need to call "back" as opposed to the user tapping the app bar's back button or the system's back button?
n
I meant that arrow back button on the TopBar
f
you can do the same, pass a lambda to your custom app bar that navigates back when called
i
If your
TopAppBar
is part of each individual screen, then yeah, you'd want to hook the click events there up to a lambda that calls
navController.navigateUp()
n
@Ian Lake yeah… that’s the case… I just wouldn’t want to pass this lamba to all screens 😞
i
How else would you test your
TopAppBar
? 😝
Navigation certainly supports both a global
TopAppBar
at a
Scaffold
level outside of your
NavHost
(that'd be appropriate if ~every screen has the same type of bar - and why the
rememberNavController()
pattern exists - to hoist the state out of the
NavHost
) or the separate
TopAppBar
in each screen (which is better if you need something custom in each)
n
Make sense… 🙃
b
Ian Lake, currently I have a global TopAppBar with a Scaffold in my MainApp composable, at what point do you determine if a TopAppBar is custom enough that you'd want to switch over to a per screen TopAppBar, running into wanting to show a "Are you sure" confirmation Dialog when pressing the back button in a Screen, the backHandler works just fine for the back button, but not the global TopAppBar which just does "navController.popBackStack()" for now. At this point I'm not sure if I should try to pass a function for what the backButton does all the way up to the main composable, or refactor to a per screen composable Sorry this thread is old and I already asked a related question in the compose-android channel.