---
title: .onMount()
description: Register one-time setup functions that run after an island is mounted into the DOM.
order: 206
---

import { Preview } from "$lib/components/preview";

export const example = `import ilha from "ilha";

export default ilha
  .onMount(({ host }) => {
    const box = host.querySelector("#box");
    if (!box) return;
    box.classList.add("bg-green-200");
  })
  .render(() => (
    <div
      id="box"
      class="rounded-lg p-4 text-green-800"
    >Hello there</div>
  ));
`

# On Mount

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.

[Interactive Tutorial](/tutorial/counter/onmount)

## Basic usage

<Preview code={example} />

## Cleanup

Return a function to run cleanup on unmount:

```tsx twoslash
import ilha from "ilha";

const Island = ilha
  .onMount(({ host }) => {
    const observer = new ResizeObserver(() => {
      console.log("resized", host.clientWidth);
    });
    observer.observe(host);

    return () => observer.disconnect(); // [!code highlight]
  })
  .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`:

```ts
{
  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:

```tsx twoslash
import ilha from "ilha";

const Island = ilha
  .onMount(({ host, hydrated }) => {
    if (!hydrated) {
      host.animate([{ opacity: 0 }, { opacity: 1 }], 300);
    }
  })
  .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:

```tsx twoslash
declare global {
  interface Window {
    MapLibrary: any;
  }
}
// ---cut---
import ilha from "ilha";

const Map = ilha
  .input<{ lat: number; lng: number }>()
  .onMount(({ host, input }) => {
    // [!code highlight:4]
    const map = new window.MapLibrary(host, {
      center: [input.lat, input.lng],
      zoom: 12,
    });

    return () => map.destroy();
  })
  .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:

```tsx twoslash
import ilha from "ilha";

const Island = ilha
  .onMount(({ host }) => {
    console.log("first", host);
  })
  .onMount(({ state }) => {
    console.log("second");
  })
  .render(() => <div>hello</div>);
```

## Skipping onMount during hydration

When using [`.hydratable()`](/guide/island/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:

```tsx twoslash
import ilha from "ilha";

const Island = ilha
  .onMount(({ host }) => {
    console.log("this is skipped on hydration");
  })
  .render(() => <div>hello</div>);

// On the server:
await Island.hydratable(
  {},
  {
    name: "my-island",
    snapshot: true,
    skipOnMount: true, // [!code highlight]
  },
);
```

## `.onMount()` vs `.effect()`

|                     | `.onMount()`                     | `.effect()`                                  |
| ------------------- | -------------------------------- | -------------------------------------------- |
| Runs                | Once after mount                 | After mount, then on every dependency change |
| Tracks signals      | No                               | Yes                                          |
| Receives `derived`  | Yes                              | Yes                                          |
| 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()`](/guide/island/effect) instead.

## Notes

- `.onMount()` runs client-side only and is never called during SSR.
- On mount, **`.onMount()` runs after the `enter` transition** (if any) and **before** [`.effect()`](/guide/island/effect) callbacks are registered. See [Transition — mount order](/guide/island/transition#mount-order).
- Throws from `.onMount()` (or its returned cleanup) are reported to [`.onError()` / `onUncaughtError()`](/guide/island/onerror) with `source: "mount"`.
- Writing to signals inside `.onMount()` is safe and will trigger a re-render.
