onMount

Registers a function that runs once after the island is mounted into the DOM. Use it for one-time setup that needs access to the host element, such as initializing third-party libraries, measuring layout, or setting up manual DOM integrations.

Basic usage

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
from "ilha";
const
const Island: Island<Record<string, unknown>, Record<string, never>>
Island
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.onMount(fn: (ctx: OnMountContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => (() => void) | void): IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>
onMount
(({
host: Element
host
}) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
("mounted",
host: Element
host
);
}) .
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(() => `<div>hello</div>`);

Cleanup

Return a function to run cleanup on unmount:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
from "ilha";
const
const Island: Island<Record<string, unknown>, Record<string, never>>
Island
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.onMount(fn: (ctx: OnMountContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => (() => void) | void): IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>
onMount
(({
host: Element
host
}) => {
const
const observer: ResizeObserver
observer
= new
var ResizeObserver: new (callback: ResizeObserverCallback) => ResizeObserver

The ResizeObserver interface reports changes to the dimensions of an Element's content or border box, or the bounding box of an SVGElement.

MDN Reference

ResizeObserver
(() => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
("resized",
host: Element
host
.
Element.clientWidth: number

The clientWidth read-only property of the Element interface is zero for inline elements and elements with no CSS; otherwise, it's the inner width of an element in pixels. It includes padding but excludes borders, margins, and vertical scrollbars (if present).

MDN Reference

clientWidth
);
});
const observer: ResizeObserver
observer
.
ResizeObserver.observe(target: Element, options?: ResizeObserverOptions): void

The observe() method of the ResizeObserver interface starts observing the specified Element or SVGElement.

MDN Reference

observe
(
host: Element
host
);
return () =>
const observer: ResizeObserver
observer
.
ResizeObserver.disconnect(): void

The disconnect() method of the ResizeObserver interface unobserves all observed Element or SVGElement targets.

MDN Reference

disconnect
();
}) .
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(() => `<div>hello</div>`);

The cleanup function is called when unmount() is invoked, just before the island tears down its listeners and effects.

Mount context

The function receives an OnMountContext:

{
  state: IslandState; // reactive state signals
  derived: IslandDerived; // current derived values
  input: TInput; // resolved input props
  host: Element; // island root element
  hydrated: boolean; // true when mounted over SSR content
}

The hydrated flag tells you whether the island was activated over existing server-rendered HTML or freshly mounted into an empty element. This is useful when you want to skip an animation or initialization step for content that is already visible:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
from "ilha";
const
const Island: Island<Record<string, unknown>, Record<string, never>>
Island
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.onMount(fn: (ctx: OnMountContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => (() => void) | void): IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>
onMount
(({
host: Element
host
,
hydrated: boolean
hydrated
}) => {
if (!
hydrated: boolean
hydrated
) {
host: Element
host
.
Animatable.animate(keyframes: Keyframe[] | PropertyIndexedKeyframes | null, options?: number | KeyframeAnimationOptions): Animation
animate
([{
opacity: number
opacity
: 0 }, {
opacity: number
opacity
: 1 }], 300);
} }) .
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(() => `<div>content</div>`);

Initializing third-party libraries

.onMount() is the right place to hand off a DOM element to a library that manages its own rendering:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
from "ilha";
const
const Map: Island<{
    lat: number;
    lng: number;
}, Record<string, never>>
Map
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.input<{
    lat: number;
    lng: number;
}>(): IlhaBuilder<{
    lat: number;
    lng: number;
}, Record<string, never>, Record<string, never>> (+1 overload)
input
<{
lat: number
lat
: number;
lng: number
lng
: number }>()
.
IlhaBuilder<{ lat: number; lng: number; }, Record<string, never>, Record<string, never>>.onMount(fn: (ctx: OnMountContext<{
    lat: number;
    lng: number;
}, Record<string, never>, Record<string, never>>) => (() => void) | void): IlhaBuilder<{
    lat: number;
    lng: number;
}, Record<string, never>, Record<string, never>>
onMount
(({
host: Element
host
,
input: {
    lat: number;
    lng: number;
}
input
}) => {
const
const map: any
map
= new
var window: Window & typeof globalThis

The window property of a Window object points to the window object itself.

MDN Reference

window
.
Window.MapLibrary: any
MapLibrary
(
host: Element
host
, {
center: number[]
center
: [
input: {
    lat: number;
    lng: number;
}
input
.
lat: number
lat
,
input: {
    lat: number;
    lng: number;
}
input
.
lng: number
lng
],
zoom: number
zoom
: 12,
}); return () =>
const map: any
map
.destroy();
}) .
IlhaBuilder<{ lat: number; lng: number; }, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<{
    lat: number;
    lng: number;
}, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<{
    lat: number;
    lng: number;
}, Record<string, never>>
render
(() => `<div style="height:400px"></div>`);

Multiple onMount hooks

Chain .onMount() as many times as needed. Each runs independently in the order it was declared:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
from "ilha";
const
const Island: Island<Record<string, unknown>, Record<string, never>>
Island
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.onMount(fn: (ctx: OnMountContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => (() => void) | void): IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>
onMount
(({
host: Element
host
}) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
("first",
host: Element
host
);
}) .
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.onMount(fn: (ctx: OnMountContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => (() => void) | void): IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>
onMount
(({
state: IslandState<Record<string, never>>
state
}) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
("second");
}) .
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(() => `<div>hello</div>`);

Skipping onMount during hydration

When using .hydratable() with snapshot: true, the skipOnMount option tells ilha to skip all .onMount() calls when the island is rehydrated from a snapshot. This is useful when your mount logic would duplicate work that was already done on the server:

import 
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
from "ilha";
const
const Island: Island<Record<string, unknown>, Record<string, never>>
Island
=
const ilha: IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>> & {
    html: (strings: TemplateStringsArray, ...values: unknown[]) => RawHtml;
    raw: (value: string) => RawHtml;
    mount: (registry: IslandRegistry, options?: MountOptions) => MountResult;
    from: <TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>) => (() => void) | null;
    context: <T>(key: string, initial: T) => ContextSignal<...>;
}
ilha
.
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.onMount(fn: (ctx: OnMountContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => (() => void) | void): IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>
onMount
(({
host: Element
host
}) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
("this is skipped on hydration");
}) .
IlhaBuilder<Record<string, unknown>, Record<string, never>, Record<string, never>>.render(fn: (ctx: RenderContext<Record<string, unknown>, Record<string, never>, Record<string, never>>) => string | RawHtml): Island<Record<string, unknown>, Record<string, never>>
render
(() => `<div>hello</div>`);
// On the server: await
const Island: Island<Record<string, unknown>, Record<string, never>>
Island
.
Island<Record<string, unknown>, Record<string, never>>.hydratable(props: Partial<Record<string, unknown>>, options: HydratableOptions): Promise<string>
hydratable
(
{}, {
HydratableOptions.name: string
name
: "my-island",
HydratableOptions.snapshot?: boolean | {
    state?: boolean;
    derived?: boolean;
} | undefined
snapshot
: true,
HydratableOptions.skipOnMount?: boolean | undefined
skipOnMount
: true,
}, );

.onMount() vs .effect()

.onMount().effect()
RunsOnce after mountAfter mount, then on every dependency change
Tracks signalsNoYes
Receives derivedYesNo
Receives hydratedYesNo
Cleanup supportYesYes
Use forOne-time setup, third-party libsReactive sync to external APIs

If you need something to stay in sync with state over time, use .effect() instead.

Notes

  • .onMount() runs client-side only and is never called during SSR.
  • The mount function runs after the first render and after all effects have been set up.
  • Writing to signals inside .onMount() is safe and will trigger a re-render.