Socket
Socket
Sign inDemoInstall

@solid-primitives/rootless

Package Overview
Dependencies
Maintainers
3
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@solid-primitives/rootless - npm Package Compare versions

Comparing version 1.3.2 to 1.4.0

61

dist/index.d.ts

@@ -1,2 +0,2 @@

import { Owner } from 'solid-js';
import { Owner, Accessor } from 'solid-js';
import { AnyFunction } from '@solid-primitives/utils';

@@ -56,3 +56,3 @@

* @returns function, registering reactive owner as one of the listeners, returns the value {@link factory} returned.
* @see https://github.com/davedbase/solid-primitives/tree/main/packages/rootless#createSingletonRoot
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/rootless#createSingletonRoot
* @example

@@ -89,3 +89,58 @@ * const useState = createSingletonRoot(() => {

declare function createHydratableSingletonRoot<T>(factory: (dispose: VoidFunction) => T): () => T;
/**
* Options for {@link createRootPool}.
*/
type RootPoolOptions = {
/**
* Size of the root pool. Defaults to `100`.
*/
limit?: number;
};
/**
* Callback function for {@link createRootPool}. Called when a new root is created.
* @param arg An accessor that returns the argument passed to {@link RootPoolFunction}.
* @param active An accessor that returns the active state of the root.
* When `false`, root is not being used and is waiting in the pool to be reused.
* @param dispose A function that disposes the root and prevents it from being reused.
* @returns The result of {@link RootPoolFunction}.
*/
type RootPoolFactory<TArg, TResult> = (arg: Accessor<TArg>, active: Accessor<boolean>, dispose: VoidFunction) => TResult;
/**
* A function returned by {@link createRootPool}.
* @param arg The argument passed to {@link RootPoolFactory}.
*/
type RootPoolFunction<TArg, TResult> = (..._: void extends TArg ? [arg?: TArg] : [arg: TArg]) => TResult;
/**
* Creates a pool of roots, that can be reused. Useful for creating components that are mounted and unmounted frequently.
* When the root is created, it will call the {@link factory} function with a {@link RootPoolFactory} callback.
* Roots are created by calling the returned function, after cleanup they won't be disposed but instead put back into the pool to be reused.
* Next time the function is called, it will reuse the root from the pool and update it with the new {@link arg}.
*
* @param factory A function that will be called when a new root is created. See {@link RootPoolFactory}.
* @param options Options for the root pool. See {@link RootPoolOptions}.
* @returns A function that creates and reuses roots. See {@link RootPoolFunction}.
*
* @see https://github.com/solidjs-community/solid-primitives/tree/main/packages/rootless#createRootPool
*
* @example
* ```tsx
* const useCounter = createRootPool((arg, active, dispose) => {
* const [count, setCount] = createSignal(arg())
*
* createEffect(() => {
* if (!active()) return
* // so some side effect
* console.log("count", count())
* })
*
* return <button onClick={() => setCount(count() + 1)}>Count: {count()}</button>
* })
*
* return <Show when={frequentlyChangedCondidion()}>
* {useCounter(1)}
* </Show>
* ```
*/
declare function createRootPool<TArg, TResult>(factory: RootPoolFactory<TArg, TResult>, options?: RootPoolOptions): RootPoolFunction<TArg, TResult>;
export { createBranch, createCallback, createDisposable, createHydratableSingletonRoot, createSharedRoot, createSingletonRoot, createSubRoot };
export { RootPoolFactory, RootPoolFunction, RootPoolOptions, createBranch, createCallback, createDisposable, createHydratableSingletonRoot, createRootPool, createSharedRoot, createSingletonRoot, createSubRoot };

@@ -1,4 +0,4 @@

import { getOwner, createRoot, runWithOwner, onCleanup, sharedConfig } from 'solid-js';
import { getOwner, createRoot, runWithOwner, onCleanup, sharedConfig, createSignal, batch } from 'solid-js';
import { isServer } from 'solid-js/web';
import { asArray, access } from '@solid-primitives/utils';
import { asArray, access, trueFn, noop, createMicrotask } from '@solid-primitives/utils';

@@ -49,3 +49,69 @@ // src/index.ts

}
function createRootPool(factory, options = {}) {
if (isServer) {
const owner2 = getOwner();
return (args) => createRoot((dispose) => factory(() => args, trueFn, dispose), owner2);
}
let length = 0;
const { limit = 100 } = options, pool = new Array(limit), owner = getOwner(), mapRoot = factory.length > 1 ? (dispose, [args, set]) => {
const [active, setA] = createSignal(true);
const root = {
dispose,
set,
setA,
active,
v: factory(args, active, () => disposeRoot(root))
};
return root;
} : (dispose, [args, set]) => ({
dispose,
set,
setA: trueFn,
active: trueFn,
v: factory(args, trueFn, noop)
}), limitPool = createMicrotask(() => {
if (length > limit) {
for (let i = limit; i < length; i++) {
pool[i].dispose();
pool[i] = void 0;
}
length = limit;
}
}), cleanupRoot = (root) => {
if (root.dispose !== noop) {
pool[length++] = root;
root.setA(false);
limitPool();
}
}, disposeRoot = (root) => {
root.dispose();
root.dispose = noop;
if (root.active())
root.setA(false);
else {
pool[pool.indexOf(root)] = pool[--length];
pool[length] = void 0;
}
};
onCleanup(() => {
for (let i = 0; i < length; i++)
pool[i].dispose();
length = 0;
});
return (arg) => {
let root;
if (length) {
root = pool[--length];
pool[length] = void 0;
batch(() => {
root.set(() => arg);
root.setA(true);
});
} else
root = createRoot((dispose) => mapRoot(dispose, createSignal(arg)), owner);
onCleanup(() => cleanupRoot(root));
return root.v;
};
}
export { createBranch, createCallback, createDisposable, createHydratableSingletonRoot, createSharedRoot, createSingletonRoot, createSubRoot };
export { createBranch, createCallback, createDisposable, createHydratableSingletonRoot, createRootPool, createSharedRoot, createSingletonRoot, createSubRoot };

15

package.json
{
"name": "@solid-primitives/rootless",
"version": "1.3.2",
"version": "1.4.0",
"description": "A collection of helpers that aim to simplify using reactive primitives outside of reactive roots, and managing disposal of reactive roots.",

@@ -19,3 +19,4 @@ "author": "Damian Tarnawski @thetarnav <gthetarnav@gmail.com>",

"createDisposable",
"createSharedRoot"
"createSharedRoot",
"createRootPool"
],

@@ -43,8 +44,10 @@ "category": "Reactivity"

"keywords": [
"solid",
"primitives",
"reactivity",
"root",
"solid",
"primitives"
"ownership"
],
"dependencies": {
"@solid-primitives/utils": "^6.0.0"
"@solid-primitives/utils": "^6.1.1"
},

@@ -55,2 +58,4 @@ "peerDependencies": {

"scripts": {
"dev": "vite serve dev",
"page": "vite build dev",
"build": "jiti ../../scripts/build.ts",

@@ -57,0 +62,0 @@ "test": "vitest -c ../../configs/vitest.config.ts",

@@ -18,2 +18,3 @@ <p>

- [`createSingletonRoot`](#createSingletonRoot) - Share "global primitives" across multiple reactive scopes.
- [`createRootPool`](#createRootPool) - Creates a pool of reactive roots, that can be reused.

@@ -171,4 +172,53 @@ ## Installation

## `createRootPool`
Creates a pool of roots, that can be reused. Useful for creating components that are mounted and unmounted frequently.
When the root is created, it will call the factory function.
Roots are created by calling the returned function, after cleanup they won't be disposed but instead put back into the pool to be reused.
Next time the function is called, it will reuse the root from the pool and update it with the new data.
### How to use it
`createRootPool` primitive takes two arguments:
- `factory` - A function that will be called when a new root is created.
- `options` - Options for the root pool.
- `limit` - Pool limit, defaults to `100`. Roots that are not used will be disposed when the limit is reached.
Returns a function that creates and reuses roots.
```tsx
import { createRootPool } from "@solid-primitives/rootless";
const useCounter = createRootPool((arg, active, dispose) => {
const [count, setCount] = createSignal(arg());
createEffect(() => {
if (!active()) return;
// so some side effect
console.log("count", count());
});
return <button onClick={() => setCount(count() + 1)}>Count: {count()}</button>;
});
return <Show when={frequentlyChangedCondidion()}>{useCounter(1)}</Show>;
```
### Usage with `<For>`
`createRootPool` can be combined with `<For>` (or any other control-flow component) to reuse already created HTML Elements while getting the same benefits of stable connection between rendered elements and the reference to the source item.
```tsx
const pool = createRootPool(item => <MyListItem item={item()}>)
return <For each={items()}>{item => pool(item)}</For>
```
> **Warning**
> Using `createRootPool` with `<For>` creates an un-keyed control-flow — meaning that a single element can be reused by more than one item (not at the same time). Which can cause styles, animations, and other side effects to leak between items.
> It's meant to be used only as a performance optimization, and only when you're sure that the side effects won't leak between items.
## Changelog
See [CHANGELOG.md](./CHANGELOG.md)

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc