use:*
Edit this pageCustom directives attach reusable behavior to DOM elements, acting as syntactic sugar over ref
. They’re ideal for complex DOM interactions like scrolling, tooltips, or form handling, which are cumbersome to repeat in JSX.
A directive is a function with the following signature
function directive(element: HTMLElement, accessor: Accessor<any>): void;
Directive functions are called at render time but before being added to the DOM. You can do whatever you'd like in them including create signals, effects, register clean-up etc.
Example
A model
directive for two-way data binding
import type { Accessor, Signal } from "solid-js";
function model(element: HTMLInputElement, value: Accessor<Signal<string>>) { const [field, setField] = value(); createRenderEffect(() => (element.value = field())); element.addEventListener("input", ({ target }) => setField(target.value));}
const [name, setName] = createSignal("");
<input type="text" use:model={[name, setName]} />;
TypeScript Support
To type custom directives, extend the DirectiveFunctions
interface
declare module "solid-js" { namespace JSX { interface DirectiveFunctions { model: typeof model; } }}
If you just want to constrain the second argument to the directive function, you can extend the older Directives
interface
declare module "solid-js" { namespace JSX { interface Directives { model: Signal<string>; } }}
Avoiding Tree-Shaking
When importing a directive d
from another module and using it only as use:d
, TypeScript (via babel-preset-typescript) may remove the import, as it doesn’t recognize use:d
as a reference to d
.
To prevent this:
-
Use the
onlyRemoveTypeImports: true
option inbabel-preset-typescript
. Forvite-plugin-solid
, add this tovite.config.ts
import solidPlugin from "vite-plugin-solid";export default {plugins: [solidPlugin({typescript: { onlyRemoveTypeImports: true }})],};Note: This requires consistent use of
export type
andimport type
in your codebase to avoid issues. -
Add a fake access like
false && d;
in the moduleimport { model } from "./directives";false && model; // Prevents tree-shaking<input type="text" use:model={[name, setName]} />;This is removed by bundlers like Terser, unlike a plain
model;
which may remain in the bundle.
Directives only work with native HTML elements (HTML/SVG/MathML/Custom Elements).
Directives are not forwarded and won't work in user defined components, such as <MyComponent use:myinput={[..]}/>
see also