Package Exports
- @solid-primitives/refs
Readme
@solid-primitives/refs
Collection of primitives, components and directives that help managing references to JSX elements, keeping track of mounted/unmounted elements.
Primitives:
mergeRefs- Utility for using jsx refs both for local variables and providing it to theprops.reffor component consumers.elements- Reactive signal that filters out non-element items from a signal array. (Can be used withchildrenprimitive)refs- Get signal references to Elements of the reactive input. Which were added, which were removed. (Can be used withchildrenprimitive)mapRemoved- Similar to Solid'smapArray, but you map the elements that were removed from source array. Leting you keep them for longer.resolveElements— Will resolve value to a flat list of HTML elements or a single element ornull.
Directive:
unmount- A directive that calls handler when the element get's unmounted from DOM.
Components:
<Children>- Solid'schildrenhelper in component form. Access it's children elements bygetproperty.<Refs>- Get up-to-date references of the multiple children elements.<Ref>- Get up-to-date reference to a single child element.
Types:
RefProps- Component properties with types forrefResolvedChildren- Type of resolved JSX elements provided by Solid'schildrenhelper.
Vanilla helpers:
getChangedItems- Tells you which elements got added to the array, and which got removedgetAddedItems- Tells you elements got added to the arraygetRemovedItems- Tells you which elements got removed from the array
Installation
npm install @solid-primitives/refs
# or
yarn add @solid-primitives/refsPrimitives
mergeRefs
Utility for using jsx refs both for local variables and providing it to the props.ref for component consumers.
How to use it
import { mergeRefs } from "@solid-primitives/refs";
interface ButtonProps {
ref?: HTMLButtonElement | ((el: HTMLButtonElement) => void);
}
const Button = (props: ButtonProps) => {
let ref!: HTMLButtonElement;
onMount(() => {
// use the local ref
});
return <button ref={mergeRefs(el => (ref = el), props.ref)} />;
};
// in consumer's component:
let ref!: HTMLButtonElement;
<Button ref={ref} />;elements
Reactive signal that filters out non-element items from a signal array. (Can be used with children primitive)
How to use it
import { elements } from "@solid-primitives/refs";
const resolved = children(() => props.children);
const els = elements(resolved);
els(); // T: Element[]
// or narrow down the element type
const divs = elements(resolved, HTMLDivElement);
divs(); // T: HTMLDivElement[]refs
Get signal references to Elements of the reactive input. Which were added, which were removed. (Can be used with children primitive)
Used internally by <Refs> component.
How to use it
import { refs } from "@solid-primitives/refs";
const resolved = children(() => props.children);
const [els, added, removed] = refs(resolved);
els(); // T: Element[]
added(); // T: Element[]
removed(); // T: Element[]
// or narrow down the element type
const [els, added, removed] = refs(resolved, HTMLDivElement);
els(); // T: HTMLDivElement[]
added(); // T: HTMLDivElement[]
removed(); // T: HTMLDivElement[]mapRemoved
Reactively map removed items from a reactive signal array. If the mapping function return an element signal, this element will be placed in the array returned from primitive.
How to use it
import { mapRemoved } from "@solid-primitives/refs";
const MyComp = props => {
const resolved = children(() => props.children);
const combined = mapRemoved(resolved, (ref, index) => {
const [el, setEl] = createSignal(ref);
// apply styles/animations to removed element
ref.style.filter = "grayscale(100%)";
// computations can be created inside the mapping fn
createEffect(() => {
// index is a signal
index();
});
const remove = () => {
// ...later
// by setting returned signal to undefined
// element get's removed from combined array permanently
setEl(undefined);
};
// you can return a signal with element to keep it in the combined array
return el;
});
return combined;
};resolveElements
Similarly to children() helper from solid-js will resolve provided value to a flat list of HTML elements or a single element or null. But doesn't create a computation.
import { resolveElements } from "@solid-primitives/refs";
const MyComponent: ParentComponent = props => {
createEffect(() => {
const resolved = resolveElements(props.children);
resolved; // T: HTMLElement | HTMLElement[] | null
});
return "Don't access props.children here again — it'll create new dom nodes";
};Directive
unmount
A directive that calls handler when the element get's unmounted from DOM.
Import
import { unmount } from "@solid-primitives/refs";
// place it somewhere in the code to prevent it from being tree-shaken
unmount;How to use it
const [ref, setRef] = createSignal<Element | undefined>();
<div ref={el => setRef(el)} use:unmount={() => setRef(undefined)}>
Hello
</div>;Components
<Children>
Solid's children helper in component form. Access it's children elements by get property.
How to use it
import {Children, ResolvedJSXElement} from "@solid-primitives/refs"
// typing as JSX.Element also works
const [children, setChildren] = createSignal<ResolvedJSXElement>([])
<Children get={setChildren}>
<div></div>
...
</Children><Ref>
Get up-to-date reference to a single child element.
Import
import { Ref } from "@solid-primitives/refs";How to use it
<Ref> accepts these properties:
ref- Getter of current element (orundefinedif not mounted)onMount- handle the child element getting mounted to the domonUnmount- handle the child element getting unmounted from the dom
const [ref, setRef] = createSignal<Element | undefined>();
<Ref
ref={setRef}
onMount={el => console.log("Mounted", el)}
onUnmount={el => console.log("Unmounted", el)}
>
<Show when={show()}>
<div>Hello</div>
</Show>
</Ref>;Providing generic Element type
<Ref<HTMLDivElement>
ref={el => {...}} // HTMLDivElement | undefined
onMount={el => {...}} // HTMLDivElement
onUnmount={el => {...}} // HTMLDivElement
>
<div>Hello</div>
</Ref><Refs>
Get up-to-date references of the multiple children elements.
Import
import { Refs } from "@solid-primitives/refs";How to use it
<Refs> accepts these properties:
refs- Getter of current array of elementsadded- Getter of added elements since the last changeremoved- Getter of removed elements since the last changeonChange- handle children changes
const [refs, setRefs] = createSignal<Element[]>([]);
<Refs
refs={setRefs}
added={els => console.log("Added elements", els)}
removed={els => console.log("Removed elements", els)}
onChange={e => console.log(e)}
>
<For each={my_list()}>{item => <div>{item}</div>}</For>
<Show when={show()}>
<div>Hello</div>
</Show>
</Refs>;Providing generic Element type
<Refs<HTMLDivElement>
refs={els => {}} // HTMLDivElement[]
added={els => {}} // HTMLDivElement[]
removed={els => {}} // HTMLDivElement[]
// { refs: HTMLDivElement[]; added: HTMLDivElement[]; removed: HTMLDivElement[] }
onChange={e => {}}
>
<div>Hello</div>
</Refs>Demo
https://stackblitz.com/edit/solid-vite-unocss-bkbgap?file=index.tsx
(run npm start in the terminal)
Types
RefProps
Component properties with types for ref
interface RefProps<T extends Element> {
ref?: T | ((el: T) => void);
}ResolvedChildren
Type of resolved JSX elements provided by Solid's children helper.
type ResolvedChildren = ResolvedJSXElement | ResolvedJSXElement[];Changelog
See CHANGELOG.md