$screen
Route parameters, navigation state, the current path, and a loader's error — one object, on the screen and in its loader.
Route Parameters
A [param] folder becomes a dynamic segment, read with $screen.params:
// File: routes/user/[id]/+screen.wh
// URL: /user/123
val userId = $screen.params.id // "123" Multiple Parameters
// File: routes/posts/[category]/[slug]/+screen.wh
// URL: /posts/tech/hello-world
val category = $screen.params.category // "tech"
val slug = $screen.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 = $screen.state?.name
val previewPoster = $screen.state?.poster
var fullData: Show? = $state(null)
@if (previewName != null) {
<Text>{previewName}</Text> // shown immediately
}
// Load full data
$onMount { fullData = $fetch("https://api.example.com/shows/$id") } Every field is a String? — the screen may have been opened by a deep link, or
by a plain $navigate("/show/${id}") that passed no state — so read it with ?. and give it a fallback.
Using in Data Loaders
$screen.params reads the same in a loader file:
// 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 State
Check for state availability before using it:
val preview = $screen.state?.preview
@if (preview != null) {
<Image src={preview.poster} />
<Text>{preview.name}</Text>
} else {
<CircularProgressIndicator />
} Current Path
$screen.path reads the current route's path, for comparing against a literal —
a bottom bar deciding which item is selected:
<BottomBarItem selected={$screen.path == "/"} href="/">Home</BottomBarItem> Errors
When a loader throws, $screen.error holds what it threw — a Throwable, read inside the nearest +error.wh:
// +error.wh
<Text>{$screen.error.message}</Text> See $data for how a loader's failure picks which +error.wh renders.
Complete Example
// routes/show/[id]/+screen.wh
val showId = $screen.params.id
val previewData = $screen.state
var show: Show? = $state(null)
var isLoading = $state(true)
suspend fun loadShow() {
show = $fetch("https://api.example.com/shows/$showId")
isLoading = false
}
$onMount { loadShow() }
<Column p={16}>
@if (isLoading && previewData != null) {
// show preview while loading
<Image src={previewData.poster} />
<Text>{previewData.name}</Text>
} else if (show != null) {
// show full data
<Image src={show.poster} />
<Text fontSize={24}>{show.name}</Text>
<Text>{show.description}</Text>
} else {
<CircularProgressIndicator />
}
</Column> See Also
- $navigate - Navigate between screens
- $data - Data loading
- Project Structure - Dynamic routes