[]previous and next page

onMount

onMount(fn) runs fn once, after the owner has been created and flushed, with tracking off.

For agentsUpdated

onMount(fn) runs fn once, after the owner has been created and flushed, with tracking off. A function returned from fn is its cleanup. It is a useEffect with no dependencies, ordered with the other effects of the component by creation. It is the place for code that needs the mounted DOM once: measuring, focusing, subscribing to a browser API.

src/focus-input.tsxtsx
import { onMount } from "@shadow-js/core";

export function FocusInput() {
  let input: HTMLInputElement | undefined;

  onMount(() => {
    input?.focus();
  });

  return <input type="text" ref={input} />;
}

Observers and refs#

A ref callback runs while the element is being built, before it is in the page: the element still belongs to its template's inert document and has no box yet, so a layout read there returns zeros. Measure and observe in onMount instead: it runs once the element is connected and owned by the document, and onCleanup disconnects the observer. A ResizeObserver created in a ref does report once the element is inserted , but that timing is not a contract, so start observers in onMount.

src/measured.tsxtsx
import { onCleanup, onMount, useStore } from "@shadow-js/core";

export function Measured() {
  const [width, setWidth] = useStore(0);
  let box: HTMLDivElement | undefined;

  onMount(() => {
    if (box === undefined) return;
    const observer = new ResizeObserver((entries) => {
      const entry = entries[entries.length - 1];
      if (entry !== undefined) setWidth(Math.round(entry.contentRect.width));
    });
    observer.observe(box);
    onCleanup(() => observer.disconnect());
  });

  return <div ref={box}>{width()}px wide</div>;
}