196 lines
5.4 KiB
Markdown
196 lines
5.4 KiB
Markdown
<p>
|
|
<img width="100%" src="https://assets.solidjs.com/banner?type=Primitives&background=tiles&project=Refs" alt="Solid Primitives Refs">
|
|
</p>
|
|
|
|
# @solid-primitives/refs
|
|
|
|
[](https://bundlephobia.com/package/@solid-primitives/refs)
|
|
[](https://www.npmjs.com/package/@solid-primitives/refs)
|
|
[](https://github.com/solidjs-community/solid-primitives#contribution-process)
|
|
|
|
Collection of primitives, components and directives that help managing references to JSX elements, keeping track of mounted/unmounted elements.
|
|
|
|
##### Primitives:
|
|
|
|
- [`mergeRefs`](#mergerefs) - Utility for chaining multiple `ref` assignments with `props.ref` forwarding.
|
|
- [`resolveElements`](#resolveelements) - Utility for resolving recursively nested JSX children to a single element or an array of elements.
|
|
- [`resolveFirst`](#resolvefirst) - Utility for resolving recursively nested JSX children in search of the first element that matches a predicate.
|
|
- [`<Refs>`](#refs) - Get up-to-date references of the multiple children elements.
|
|
- [`<Ref>`](#ref) - Get up-to-date reference to a single child element.
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
npm install @solid-primitives/refs
|
|
# or
|
|
pnpm add @solid-primitives/refs
|
|
# or
|
|
yarn add @solid-primitives/refs
|
|
```
|
|
|
|
## `mergeRefs`
|
|
|
|
Utility for chaining multiple `ref` assignments with `props.ref` forwarding.
|
|
|
|
### How to use it
|
|
|
|
```tsx
|
|
import { mergeRefs, Ref } from "@solid-primitives/refs";
|
|
|
|
interface ButtonProps {
|
|
ref?: Ref<HTMLButtonElement>;
|
|
}
|
|
|
|
function Button(props: ButtonProps) {
|
|
let ref: HTMLButtonElement | undefined;
|
|
onMount(() => {
|
|
// use the local ref
|
|
});
|
|
|
|
return <button ref={mergeRefs(props.ref, el => (ref = el))} />;
|
|
}
|
|
|
|
// in consumer's component:
|
|
let ref: HTMLButtonElement | undefined;
|
|
<Button ref={ref} />;
|
|
```
|
|
|
|
## `resolveElements`
|
|
|
|
Utility for resolving recursively nested JSX children to a single element or an array of elements using a predicate.
|
|
|
|
### How to use it
|
|
|
|
`resolveElements`'s API is similar to Solid's `children` helper. It accepts a function that returns JSX children and a predicate function that filters the elements.
|
|
|
|
```tsx
|
|
function Button(props: ParentProps) {
|
|
const children = resolveElements(() => props.children);
|
|
// ^?: Accessor<Element | Element[] | null>
|
|
|
|
return (
|
|
// Similarly to `children` helper, a `toArray` method is available
|
|
<For each={children.toArray()}>
|
|
{child => (
|
|
<div>
|
|
{child.localName}: {child}
|
|
</div>
|
|
)}
|
|
</For>
|
|
);
|
|
}
|
|
```
|
|
|
|
### Using a custom predicate
|
|
|
|
The default predicate is `el => el instanceof Element`. You can provide a custom predicate to `resolveElements` to filter the elements.
|
|
|
|
```tsx
|
|
const els = resolveElements(
|
|
() => props.children,
|
|
(el): el is HTMLDivElement => el instanceof HTMLDivElement,
|
|
);
|
|
|
|
els(); // => HTMLDivElement | HTMLDivElement[] | null
|
|
```
|
|
|
|
On the server side the custom predicate will be ignored, but can be overridden by passing it as a third argument.
|
|
|
|
The default predicate can be imported from `@solid-primitives/refs`:
|
|
|
|
```tsx
|
|
import { defaultElementPredicate } from "@solid-primitives/refs";
|
|
```
|
|
|
|
On the client it uses `instanceof Element` check, on the server it checks for the object with `t` property. (generated by compiling JSX)
|
|
|
|
## `resolveFirst`
|
|
|
|
Utility for resolving recursively nested JSX children in search of the first element that matches a predicate.
|
|
|
|
### How to use it
|
|
|
|
`resolveFirst` matches the API of [`resolveElements`](#resolveelements) but returns only the first element that matches the predicate.
|
|
|
|
```tsx
|
|
function Button(props: ParentProps) {
|
|
const child = resolveFirst(() => props.children);
|
|
// ^?: Accessor<Element | null>
|
|
|
|
return (
|
|
<div>
|
|
{child()?.localName}: {child()}
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
`resolveFirst` also accepts a custom predicate as a second argument. See [`Using a custom predicate`](#using-a-custom-predicate) section for more details.
|
|
|
|
## `<Ref>`
|
|
|
|
Get up-to-date reference to a single child element.
|
|
|
|
### How to use it
|
|
|
|
`<Ref>` accepts only a `ref` property for getting the current element or `undefined`, and requires `children` to be passed in.
|
|
|
|
```tsx
|
|
import { Ref } from "@solid-primitives/refs";
|
|
|
|
const [ref, setRef] = createSignal<Element | undefined>();
|
|
|
|
<Ref ref={setRef}>{props.children}</Ref>;
|
|
```
|
|
|
|
## `<Refs>`
|
|
|
|
Get up-to-date references of the multiple children elements.
|
|
|
|
### How to use it
|
|
|
|
`<Refs>` accepts only a `ref` property for getting the current array of elements, and requires `children` to be passed in.
|
|
|
|
```tsx
|
|
import { Refs } from "@solid-primitives/refs";
|
|
|
|
const [refs, setRefs] = createSignal<Element[]>([]);
|
|
|
|
<Refs ref={setRefs}>
|
|
<For each={my_list()}>{item => <div>{item}</div>}</For>
|
|
<Show when={show()}>
|
|
<div>Hello</div>
|
|
</Show>
|
|
</Refs>;
|
|
```
|
|
|
|
#### Demo
|
|
|
|
https://stackblitz.com/edit/solid-vite-unocss-bkbgap?file=index.tsx
|
|
|
|
(run `npm start` in the terminal)
|
|
|
|
## Types
|
|
|
|
### `Ref`
|
|
|
|
Type for the `ref` prop
|
|
|
|
```ts
|
|
export type Ref<T> = T | ((el: T) => void) | undefined;
|
|
```
|
|
|
|
### `RefProps`
|
|
|
|
Component properties with types for `ref` prop
|
|
|
|
```ts
|
|
interface RefProps<T> {
|
|
ref?: Ref<T>;
|
|
}
|
|
```
|
|
|
|
## Changelog
|
|
|
|
See [CHANGELOG.md](./CHANGELOG.md)
|