Refs
Edit this pageRefs, 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
JSX can be used as a value and assigned to a variable when looking to directly access DOM elements.
This lets you create and access DOM elements similar to document.createElement
but without having to wait until it is attached to the DOM.
It can be used multiple times without having to worry about duplicate selectors.
The downside of this approach is that it separates the element and any child elements from the rest of the JSX structure. This makes the component's JSX structure more difficult to read and understand.
Refs in Solid
Solid provides a ref system to access DOM elements directly inside the JSX template, which keeps the structure of the elements intact.
To use ref
, you declare a variable and use it as the ref
attribute:
These assignments occur at creation time prior to the element being added to the DOM.
If access to an element is needed before it is added to the DOM, you can use the callback form of ref
:
In TypeScript, you must use a definitive assignment assertion. Since Solid takes care of assigning the variable when the component is rendered, this signals to TypeScript that the variable will be assigned, even if it can't confirm it.
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.
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.
You can see a detailed view of the ref update lifecycle in this Solid playground example.
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:
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:
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:
- creating signals
- initiating effects
- adding event listeners
- and more.
To learn more about directives and how they work with TypeScript, refer to our TypeScript for Solid guide.