I am having a problem with NavGraph whereby using ...
# compose
u
I am having a problem with NavGraph whereby using nested graphs gives me the following obscure error:
java.lang.IllegalArgumentException: Destination Destination(0x4270f667) route=/login cannot have the same route as graph ComposeNavGraph(0x4270f667) route=/login startDestination=0x0
the code in question:
NavHost(
navController = navController,
startDestination = "/login",
) {
composable(route = "/login") {
LoginScreen(loginViewModel::onEvent, loginViewModel.state)
}
navigation(
startDestination = "/suryer",
route = "/suryer"
) {
composable(route = "/suryer") {
HomeScreen()
}
}
}
b
i don't feel its the problem with login but maybe try to change the /suryer route of the graph and the composable as both are same maybe change that to some other name
yes that is the case infact
java.lang.IllegalArgumentException: Destination Destination(0x17f98b58) route=/suryer cannot have the same route as graph ComposeNavGraph(0x17f98b58) route=/suryer startDestination=0x0
@0xf1f1 this is the error i got using your code
u
its the
navigation() fun
that is causing the issue. doesnt matter what I change it to, it gives me the same eror
b
Copy code
NavHost(
    navController = rememberNavController(),
    startDestination = "/login",
) {
    composable(route = "/login") {
        Box(modifier = Modifier.fillMaxSize())
    }
    navigation(
        startDestination = "/suryer",
        route = "/suryers"
    ) {
        composable(route = "/suryers") {
            Box {

            }
        }
    }
}
try this once this works for me
@0xf1f1 check the import of navigation is it correct but i think the change in name should solve it
u
Copy code
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.navigation
b
Copy code
import androidx.navigation.navigation
use this @0xf1f1
s
androidx.navigation.compose.navigation
is correct for what they’re trying to do. I think you just need to not use the same route for a navgraph and then the same one for one of the destinations. This is also a bit wrong since you mark the startDestination as the nav graph’s route, and not of the child route. Do something like this instead and it should work
Copy code
NavHost(
        navController = navController,
        startDestination = "/login",
    ) {
        composable(route = "/login") {
            LoginScreen(loginViewModel::onEvent, loginViewModel.state)
        }
        navigation(
            route = "/suryer"
            startDestination = "/suryerhome",
        ) {
            composable(route = "/suryerhome") {
                HomeScreen()
            }
        }
}
And then just rename appropriately. Or just ditch the strings completely and use this to have an easier time overall with this
b
@Stylianos Gakis ya sorry copied the wrong one 🥲
👍 1
s
ya sorry copied the wrong one
Yeap, an easy thing to miss. And it’s especially problematic when you do it in your code itself and then you got bugs which you have no idea about due to the string nature of this API. I am mostly suggesting the kiwi-navigation one because that’s exactly the same approach that the official navigation library is also working on right as we speak to provide first party support for type-safety in navigation. You can look at the work being done here https://issuetracker.google.com/issues/188693139 by looking at the commits there. So if you go with that, migrating to 1st party support should be completely effortless. Read comment #12 here or see this commit for proof
u
Thanks @Stylianos Gakis - the changes you suggested were in the right direction but didn't initially work until I also made the route unique. What exactly is the route variable for ?
NavHost(
navController = navController,
startDestination = "/login",
) {
composable(route = "/login") {
LoginScreen(loginViewModel::onEvent, loginViewModel.state)
}
navigation(
startDestination = "/suryer",
route = "suryer_route"
) {
composable(route = "/suryerhome") {
HomeScreen()
}
}
}
s
Copy code
navigation(
            startDestination = "/suryer",
            route = "suryer_route"
        ) {
            composable(route = "/suryerhome") {
                HomeScreen()
            }
        }
This is also wrong because the start destination is not pointing to any route in its children.
Think of
route
as the url of a website, every page you have has to be unique. Then as far as
navigation
and the root NavHost goes, it’s a bit more special where the route to that also has to be unique, but navigating to that one won’t show some UI from there, but it will then go to the route of the
startDestination
and then show that instead. I suggest reading the navigation docs to understand all this a bit better if you want to work more with this. Like this page for example https://developer.android.com/guide/navigation/design/nested-graphs
In that sample, navigating to
navController.navigate("gameInProgress")
will in fact go to
composable("match")
, since it’s the start destination of it.
👍 1
u
thanks!
I hve one more question. should routes/destinations follow the same pattern as a website URL ? i.e.
navigation(route = "auth") {  composable(route = "/auth/login") {} }
s
We don't do that ourselves, don't think there's any strong reason to do that. I am not aware of any at least
👍 1
u
Thanks! I am trying to modularise my code but getting the following error:
java.lang.IllegalArgumentException: navigation destination login is not a direct child of this NavGraph
Copy code
@Composable
fun NavGraph(navController: NavHostController) {
    NavHost(
        navController = navController,
        startDestination = NavRoute.Auth.Login.path
    ) {
        auth(this)
    }
}

private fun auth(
    builder:       NavGraphBuilder,
) {
    builder.navigation(
        startDestination = NavRoute.Auth.Login.path,
        route = NavRoute.Auth.route
    ) {
        composable(route = NavRoute.Auth.Login.path) {
            LoginScreen()
        }
    }
}
I want to use navigation() to group similar routes but it seems like the compiler doesnt like this
s
Your graph looks like this now:
Copy code
NavHost
|
|-> NavRoute.Auth.route (nested nav graph)
  |
  |-> NavRoute.Auth.Login.path (composable)
You are trying to make
NavRoute.Auth.Login.path (composable)
the start destination of NavHost, but that’s not possible since it’s not a child of it. What you probably want here is for
NavRoute.Auth.route
to be the start destination of NavHost, which will then in turn go to the start destination of
NavRoute.Auth.route
which is
NavRoute.Auth.Login.path
👍 1
u
perfect. Thanks Stylianos
🙌 1