Law

Migrating to type-safe navigation

In case I forget, this is how I migrated to Compose’s type-safe navigation.

import kotlinx.serialization.Serializable

@Serializable
object Job

And then inside the NavHost

composable<Job> {
    JobNavigation(
        jobViewModel = jobViewModel,
        navHostController,
    )
}

Passing a value

Currently, when opening the job details page, I need to pass an integer ID.

bottomNavHostController.navigate("${JobAppRoutes.JOBDETAILS_ROUTE}/${jobData.id}")

Right now inside my NavHost

composable(
    route = "${JobAppRoutes.JOBDETAILS_ROUTE}/{${JobAppRoutes.JOBDETAILS_ID}}",
    arguments =
        listOf(
            navArgument(JobAppRoutes.JOBDETAILS_ID) {
                type = NavType.IntType
            },
        ),
) { navBackStackEntry ->
    val arguments = requireNotNull(navBackStackEntry.arguments)
    val jobData =
        jobViewModel.jobList.filter {
            it.id == arguments.getInt(JobAppRoutes.JOBDETAILS_ID)
        }
}

So much going on.

Let’s migrate this to type-safe.

import kotlinx.serialization.Serializable

@Serializable
data class JobDetail(val id: Int)

Replace our code block inside our NavHost

composable<JobDetail> { backStackEntry ->
    val jobDetail: JobDetail = backStackEntry.toRoute()
    val jobDetailId = jobDetail.id
}

And lastly, replace our navigate call.

val jobDetail = JobDetail(id = jobData.id)
bottomNavHostController.navigate(jobDetail)