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 tree | ✓ | only if stored manually |
Reactive setup with effect | needs external variable | ✓ natural fit |
| One-off setup at creation | works | ✓ simpler |
| Multiple refs on one element | use several createRef | combine 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);