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: trueoption inbabel-preset-typescript. Forvite-plugin-solid, add this tovite.config.tsimport solidPlugin from "vite-plugin-solid";export default {plugins: [solidPlugin({typescript: { onlyRemoveTypeImports: true }})],};Note: This requires consistent use of
export typeandimport typein 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