Describe the bug
Prop defaults defined with $props() destructuring are not reactive to changes in the reactive values they reference. The fallback is evaluated once (with untrack()) and cached — subsequent changes to the underlying $state are never reflected.
This affects any pattern where a prop default calls a reactive function:
<script>
import { getTranslation } from './translations.svelte.js';
let { label = getTranslation('greeting') } = $props();
</script>
If getTranslation('greeting') returns "Hello" at mount time and later changes to "Hola", the component will always display "Hello".
Root cause
In the compiled output, $props() destructuring with a default becomes:
label = $.prop($$props, 'label', 19, () => getTranslation('greeting'))
Flag 19 includes PROPS_IS_LAZY_INITIAL (16). Inside $.prop, the fallback function is evaluated with untrack() and cached via a fallback_dirty flag that is only reset when the prop is explicitly provided and then removed — not when the reactive dependencies of the fallback change.
Reproduction
https://svelte.dev/playground/23fb040dbc894601979d7e6e8dc8d633
The reproduction has 3 cases:
- Direct template usage —
{getTranslation('greeting')} in template markup → updates correctly ✅
- Prop default on eagerly rendered component —
let { label = getTranslation('greeting') } = $props() on a component that mounts before the state changes → stays stale ❌
- Prop default on lazily mounted component — same code, but the component mounts after the state changes → shows the updated value ✅ (because the fallback is evaluated after the change, but it's still cached from that point forward)
Logs
No response
System Info
Svelte 5 (latest playground version)
Severity
annoyance
Describe the bug
Prop defaults defined with
$props()destructuring are not reactive to changes in the reactive values they reference. The fallback is evaluated once (withuntrack()) and cached — subsequent changes to the underlying$stateare never reflected.This affects any pattern where a prop default calls a reactive function:
If
getTranslation('greeting')returns"Hello"at mount time and later changes to"Hola", the component will always display"Hello".Root cause
In the compiled output,
$props()destructuring with a default becomes:Flag
19includesPROPS_IS_LAZY_INITIAL(16). Inside$.prop, the fallback function is evaluated withuntrack()and cached via afallback_dirtyflag that is only reset when the prop is explicitly provided and then removed — not when the reactive dependencies of the fallback change.Reproduction
https://svelte.dev/playground/23fb040dbc894601979d7e6e8dc8d633
The reproduction has 3 cases:
{getTranslation('greeting')}in template markup → updates correctly ✅let { label = getTranslation('greeting') } = $props()on a component that mounts before the state changes → stays stale ❌Logs
No response
System Info
Severity
annoyance