JUST DOMJUST-DOM
Core

createRef

Create a typed reference to a DOM element

createRef creates a mutable reference object that can be attached to an element via the ref prop, giving you access to the underlying DOM element after creation.

The ref prop also accepts a callback (el) => void directly — no createRef needed when you only need the element inside that same scope.

Import

import { createRef } from "just-dom";

Signature

function createRef<T extends JDAllTags>(): JDRef<T>;

The ref prop type on any element accepts either form:

ref?: JDRef<T> | ((el: JDTagsMap[T]) => void)

Object ref (createRef)

Use createRef when you need to access the element from outside the tree — e.g. in event handlers defined elsewhere, or in imperative code that runs after mount.

import DOM, { createRef } from "just-dom";

const inputRef = createRef<"input">();

const input = DOM.input({
  ref: inputRef,
  type: "text",
  placeholder: "Type here...",
});

// Access the element anywhere in scope
console.log(inputRef.current?.value);

inputRef.current is null until the element is created, then HTMLInputElement.

Callback ref

Use a callback when you only need the element at creation time — to set up effects, store it manually, or run one-off setup. No separate variable needed.

DOM.div({
  ref: (el) => {
    el.style.background = "papayawhip";
    el.setAttribute("data-ready", "true");
  },
});

The callback runs synchronously right after attributes are applied, before children are appended.

You can store the element manually and set up effects in the same callback:

import { createRef } from "just-dom";
import { effect } from "@just-dom/signals";

const [active, setActive] = createSignal(false);
const btnRef = createRef<"button">();

DOM.button({
  ref: (el) => {
    btnRef.current = el;           // store for external access
    effect(el, () => {             // reactive setup, self-cleaning
      el.className = active() ? "on" : "off";
    });
  },
  onclick: () => setActive((a) => !a),
}, ["Toggle"]);

Choosing between the two

Object ref (createRef)Callback ref
Access from outside the treeonly if stored manually
Reactive setup with effectneeds external variable✓ natural fit
One-off setup at creationworks✓ simpler
Multiple refs on one elementuse several createRefcombine in one callback

Examples

Form with object refs

import DOM, { createRef, createRoot } from "just-dom";

const nameRef  = createRef<"input">();
const emailRef = createRef<"input">();

const form = DOM.form(
  {
    onsubmit: (e: SubmitEvent) => {
      e.preventDefault();
      console.log({
        name:  nameRef.current?.value,
        email: emailRef.current?.value,
      });
    },
  },
  [
    DOM.input({ ref: nameRef,  type: "text",  placeholder: "Name" }),
    DOM.input({ ref: emailRef, type: "email", placeholder: "Email" }),
    DOM.button({ type: "submit" }, ["Submit"]),
  ],
);

createRoot("app", form);

Reactive styles with callback ref

import DOM, { createRoot } from "just-dom";
import { createSignal, effect, reactive } from "@just-dom/signals";

const [dark, setDark] = createSignal(false);

const card = DOM.div(
  {
    ref: (el) => {
      effect(el, () => {
        el.style.background = dark() ? "#1e293b" : "#f8fafc";
        el.style.color      = dark() ? "#e2e8f0" : "#0f172a";
      });
    },
    style: { padding: "24px", borderRadius: "8px" },
  },
  [
    DOM.p({}, [reactive(() => dark() ? "Dark mode" : "Light mode")]),
    DOM.button({ onclick: () => setDark((d) => !d) }, ["Toggle"]),
  ],
);

createRoot("app", card);

Canvas drawing (object ref)

import DOM, { createRef, createRoot } from "just-dom";

const canvasRef = createRef<"canvas">();

const app = DOM.div({}, [
  DOM.canvas({ ref: canvasRef, width: "400", height: "300" }),
  DOM.button({
    onclick: () => {
      const ctx = canvasRef.current?.getContext("2d");
      if (!ctx) return;
      ctx.fillStyle = "blue";
      ctx.fillRect(50, 50, 100, 100);
    },
  }, ["Draw"]),
]);

createRoot("app", app);

On this page