Concepts

Refs

Edit this page

Refs, or references, are a special attribute that can be attached to any element, and are used to reference a DOM element or a component instance. They are particularly useful when you need to access the DOM nodes directly or invoke methods on a component.


Accessing DOM elements

One way of accessing DOM elements is through element selectors such as document.querySelector or document.getElementById. Since elements in Solid can be added or removed from the DOM based on state, you need to wait until the element is attached to the DOM before accessing it. This can be done by using onMount to wait until the element is attached to the DOM before accessing it:

Accessing DOM elements through element selectors is not recommended for this reason. As elements with the same selectors are added and removed from the DOM, the first element that matches the selector will be returned, which may not be the element you want.


JSX as a value

When wanting to directly access the DOM element, you can use JSX as a value and assign it to a variable.

function Component() {
const myElement = <div>My Element</div>
return <div>{myElement}</div>
}

This can be a convenient way to access the DOM element. It lets you access the element directly without having to wait until it is attached to the DOM, and it can be used multiple times without having to worry about duplicate selectors.

The downside to this approach is it separates the element and any child elements that are created from it from the rest of the DOM. This removes the ability to access the element directly from the variable, and reading through components that use JSX as a value can be more difficult to understand.


Refs in Solid

Solid provides a ref system that allows you to access the DOM element directly without having to wait until it is attached to the DOM. These assignments occur at creation time prior to the element being added to the DOM. This provides access directly to the elements for manipulation, such as animations and event handling.

To use ref, you declare a variable and use it as the ref attribute:

let myElement;
<div ref={myElement}>My Element</div>

Signals as refs

Signals can also be used as refs. This is useful when you want to access the element directly, but the element may not exist when the component is first rendered, or may be removed from the DOM at some point.

function App() {
const [show, setShow] = createSignal(false)
const [element] = createSignal()
return (
<div>
<button onClick={() => setShow((isShown) => !isShown)}>Toggle</button>
<Show when={show()}>
<p ref={element()}>This is the ref element</p>
</Show>
</div>
)
}

In this example, the paragraph element is only rendered when the show signal is true. When the component initializes, the paragraph element does not exist, so the element variable is not assigned. Once the show signal is set to true, the paragraph element is rendered, and the element variable is assigned to the paragraph element.

If you would like to see a detailed example of how refs are created and used, you can view an intera

visit this Solid playground example. In this example, you can see when the element variable is assigned, and when it is removed.


Forwarding refs

Forwarding refs is a technique that allows you to pass a ref from a parent component to a child component. This is useful when you want to access the DOM element of a child component from the parent component.

To forward a ref, you need to pass the ref to the child component, and then assign the ref to the child component's element.

When a child component receives a ref attribute from its parent, the ref is passed as a callback function. This is regardless of whether the parent passed it as a simple assignment or a callback.

Once the child component receives the ref, it can be assigned to the element that the child component wants to expose through the ref attribute. To access the ref in the child component, it is passed as a prop:

// Parent component
import { Canvas } from "./Canvas.jsx"
function ParentComponent() {
let canvasRef
const animateCanvas = () => {
// Manipulate the canvas using canvasRef...
}
return (
<div>
<Canvas ref={canvasRef} />
<button onClick={animateCanvas}>Animate Canvas</button>
</div>
)
}
// Child component
function Canvas(props) {
return (
<div className="canvas-container">
<canvas ref={props.ref} /> {/* Assign the ref to the canvas element */}
</div>
)
}

In this example, the canvas element is directly assigned the ref attribute through the props.ref variable. This forwards the reference to the parent component, giving it direct access to the canvas element.


Directives

Directives allow the attachment of reusable behaviours to DOM elements. The use: prefix is used to denote these custom directives. Unlike props or attributes, directives operate at a lower level through providing fine-grained control over the elements they are attached to.

Directives are like callback refs but they enable two extra features:

  • Having multiple directives on an element.
  • Passing in reactive data to the callback.

A directive is essentially a function with a specific signature:

function directive(element: Element, accessor: () => any): void
  • element: The DOM element that the directive is applied to.
  • accessor: A function that gives access to the value(s) passed to the directive.

The directive functions are called at render time, but are called before the element is added to the DOM. Due to this order, elements are fully primed with their attributes, properties, or event listeners, therefore minimizing unexpected behaviors or premature interactions.

Within directives, you're able to perform a variety of tasks, including:

To learn more about directives and how they work with TypeScript, refer to our TypeScript for Solid guide.

Report an issue with this page