Documentation

$route / $screen

Access route parameters and navigation state.

Route Parameters

Access dynamic route segments:

// File: routes/user/[id]/+screen.wh
// URL: /user/123

val userId = $route.params.id        // "123"
val userId = $screen.params.id       // Same thing ($screen is alias)

Multiple Parameters

// File: routes/posts/[category]/[slug]/+screen.wh
// URL: /posts/tech/hello-world

val category = $route.params.category  // "tech"
val slug = $route.params.slug          // "hello-world"

Navigation State

Access data passed via $navigate:

// From previous screen
$navigate("/show/${id}", state = {
  name: show.name,
  poster: show.poster
})

// In destination screen
val previewName = $route.state?.name
val previewPoster = $route.state?.poster

@if (previewName != null) {
  <Text>{previewName}</Text>  // Show immediately
}

// Load full data
$onMount { fullData = $fetch(".../$id") }

Using in Data Loaders

Access params in loader files:

// routes/user/[id]/+screen.load.wh
suspend fun load(): User {
  val userId = $screen.params.id
  return $fetch("https://api.example.com/users/$userId")
}

// routes/user/[id]/+screen.wh
<Column>
  <Text>{$data.name}</Text>
  <Text>{$data.email}</Text>
</Column>

Optional Parameters

Check for state availability:

val preview = $route.state?.preview

@if (preview != null) {
  <Image src={preview.poster} />
  <Text>{preview.name}</Text>
} else {
  <CircularProgressIndicator />
}

$route vs $screen

These are aliases - use whichever reads better:

  • $route.params - Emphasizes routing concept
  • $screen.params - Emphasizes screen context

Both access the same underlying data.

Complete Example

// routes/show/[id]/+screen.wh
val showId = $route.params.id
val previewData = $route.state

var show: Show? = null
var isLoading = true

suspend fun loadShow() {
  show = $fetch("https://api.example.com/shows/$showId")
  isLoading = false
}

$onMount { loadShow() }

<Column p={16}>
  @if (isLoading && previewData != null) {
    
    <Image src={previewData.poster} />
    <Text>{previewData.name}</Text>
  } else if (show != null) {
    
    <Image src={show.poster} />
    <Text fontSize={24}>{show.name}</Text>
    <Text>{show.description}</Text>
  } else {
    <CircularProgressIndicator />
  }
</Column>

See Also