Element refs: ref
A ref is access to the real DOM element created by JSX. You need it when an element must do something attributes cannot express: focus an input, scroll a list, measure a size, hook up a third-party library.
A ref into a variable
In Solid JSX creates real DOM nodes, so a ref is an ordinary variable that Solid writes the element into:
// src/components/NewTodo.jsx
import { onMount } from 'solid-js';
export default function NewTodo() {
let input;
onMount(() => {
input.focus();
});
return <input ref={input} placeholder="New task" />;
}Render <NewTodo /> in src/App.jsx. After the page loads, the cursor is already in the input. The variable is declared with let because Solid assigns it when the element is created.
When the element is available
| Place | Value of input |
|---|---|
Component body, before return | undefined, the element does not exist yet |
onMount | The element, already in the page |
| Event handler | The element |
That is why ref work goes into onMount, effects and handlers.
A ref in a handler
After adding a task it is handy to clear the field and put the focus back into it:
// src/components/NewTodo.jsx
export default function NewTodo(props) {
let input;
const add = () => {
props.onAdd(input.value);
input.value = '';
input.focus();
};
return (
<div>
<input ref={input} placeholder="New task" />
<button onClick={add}>Add</button>
</div>
);
}Usage: <NewTodo onAdd={(title) => console.log(title)} />. After the click the text goes to the console, the field is cleared and the cursor returns to it.
A function ref
You can pass a function to ref. Solid calls it with the element right after creation:
// src/components/TodoList.jsx
export default function TodoList() {
return (
<ul ref={(el) => console.log('List created', el)}>
<li>Buy milk</li>
</ul>
);
}The console shows a message with the ul element. This form is needed, for example, to pass the element up to a parent through a prop.
Common mistake
Declaring a ref with const or using it in the component body:
// src/components/NewTodo.jsx
export default function NewTodo() {
let input;
// Wrong: the element does not exist yet
// input.focus();
return <input ref={input} />;
}While the component body runs, the element is not created yet, and input.focus() throws an error. With const Solid cannot write the element into the variable. Use let and access the ref in onMount or in handlers.