#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[]): voidThe console.log() static method outputs a message to the console.
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) => ResizeObserverThe ResizeObserver interface reports changes to the dimensions of an Element's content or border box, or the bounding box of an SVGElement.
ResizeObserver (() => {
var console: Console console .Console.log(...data: any[]): voidThe console.log() static method outputs a message to the console.
log ("resized", host: Element host .Element.clientWidth: numberThe 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).
clientWidth );
});
const observer: ResizeObserver observer .ResizeObserver.observe(target: Element, options?: ResizeObserverOptions): voidThe observe() method of the ResizeObserver interface starts observing the specified Element or SVGElement.
observe (host: Element host );
return () => const observer: ResizeObserver observer .ResizeObserver.disconnect(): voidThe disconnect() method of the ResizeObserver interface unobserves all observed Element or SVGElement targets.
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 globalThisThe window property of a Window object points to the window object itself.
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[]): voidThe console.log() static method outputs a message to the console.
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[]): voidThe console.log() static method outputs a message to the console.
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[]): voidThe console.log() static method outputs a message to the console.
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() | |
|---|---|---|
| Runs | Once after mount | After mount, then on every dependency change |
| Tracks signals | No | Yes |
Receives derived | Yes | No |
Receives hydrated | Yes | No |
| Cleanup support | Yes | Yes |
| Use for | One-time setup, third-party libs | Reactive 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.