--- title: 'Passing props to islands' slug: island-props description: 'How props are serialized and passed to hydratable islands, including supported types and auto-injected framework props.' --- ## Passing props to islands Pass props to a component marked with `mochi:hydrate`, `mochi:hydrate:visible`, or `mochi:defer` exactly as you would to any Svelte component — the framework serializes them with [`devalue`](https://github.com/Rich-Harris/devalue) so the same values reach the hydrating client. ```svelte ``` Do **NOT** pass functions, class instances, or `Symbol` values as props; instead, send a plain-data representation and rebuild the value inside the island. ### Typing props Put the type on the `let { … } = $props()` declaration — don't pass a type argument to `$props()` itself. For a handful of props, inline the type after the destructuring: ```svelte ``` For larger or reused shapes, pull it out into a `Props` interface: ```svelte ``` Avoid the `$props<{ … }>()` type-argument form — always annotate the `let { … }` declaration as shown above. Snippet props (including `children`) are typed with the `Snippet` interface from `svelte`: ```svelte {@render children()} ``` When a component wraps a native element and forwards the rest of its attributes, type the spread with the matching interface from [`svelte/elements`](https://svelte.dev/docs/svelte/typescript#Typing-wrapper-components): ```svelte ``` ### Wire format For `mochi:hydrate*` islands, props are emitted as a ` ``` - `isHydratable` — `true` when the call site uses `mochi:hydrate`, `mochi:hydrate:visible`, or `mochi:defer mochi:hydrate`. Undefined for pure SSR-only invocations and for bare `mochi:defer`. Do **NOT** declare `isHydratable` as a user-controlled prop; instead, treat it as an input the framework owns. See `Selective hydration with mochi:hydrate` for the branching pattern. For a unique per-instance id, use Svelte's native `$props.id()` instead of a prop. `islandId` is a reserved name on every island (`mochi:hydrate` and `mochi:defer` alike) — passing it as a literal prop is a compile error, so a component can move between directives without the name silently changing meaning. On `mochi:defer` it is also the framework's transport key inside the signed envelope, stripped server-side before the component renders; a spread carrying it there is overridden by the framework value (last key wins). For a unique id inside the component, use `$props.id()`.