@solid-primitives/memo

Collection of custom createMemo
primitives. They extend it's functionality while keeping the usage similar.
Installation
npm install @solid-primitives/memo
yarn add @solid-primitives/memo
createWritableMemo
Solid's createMemo
which value can be overwritten by a setter.
How to use it
createWritableMemo
takes the same arguments as Solid's createMemo
:
calc
- callback that calculates the valuevalue
- initial value (for calcultion)options
- give a name to the reactive computation, or change equals
method.
And returns a signal with value of the last change, set by a setter or a memo calculation.
const [count, setCount] = createSignal(1);
const [result, setResult] = createWritableMemo(() => count() * 2);
setResult(5);
createLazyMemo
Lazily evaluated createMemo
. Will run the calculation only if is being listened to.
How to use it
It's usage is almost the same as Solid's createMemo
. Similarly it should be placed inside a reactive root — component or createRoot.
import { createLazyMemo } from "@solid-primitives/memo";
const double = createLazyMemo(() => count() * 2);
double();
Set the initial value, or type of the previous value in calculation function will be T | undefined
.
const memo = createLazyMemo(prev => count() + prev, 123);
memo();
See the tests for better usage reference.
Demo
https://codesandbox.io/s/solid-primitives-memo-demo-3w0oz?file=/index.tsx
createAsyncMemo
Solid's createMemo
that allows for asynchronous calculations.
How to use it
It's usage is almost the same as Solid's createMemo
. Similarly it should be placed inside a reactive root — component or createRoot.
The function argument can return a promise. Promises will be handled with preserving the order of execution, that means if a promise would take more time to execute it won't overwrite thouse that start after it but finish quicker.
import { createAsyncMemo } from "@solid-primitives/memo";
const memo = createAsyncMemo(
async prev => {
const value = await myAsyncFunc(signal());
return value.data;
},
{ value: "initial value" }
);
calculation will track reactive reads synchronously — stops tracking after first await
const memo = createAsyncMemo(async prev => {
const value = await myAsyncFunc(signal());
const data = otherSignal() + value;
return value;
});
Demo
Demo uses fetching because it is the simplest example to make, but please don't use it instead of createResource for fetching data.
https://codesandbox.io/s/solid-primitives-async-memo-fetch-demo-htne6?file=/index.tsx
const [data] = createResource(signal, value => {...})
createDebouncedMemo
Solid's createMemo
which returned signal is debounced.
How to use it
import { createDebouncedMemo } from "@solid-primitives/memo";
const double = createDebouncedMemo(prev => count() * 2, 200);
const double = createDebouncedMemo(prev => count() * 2, 200, { value: 0 });
Notes:
- the callback is not perfectly debounced, it will be fired twice for each debounce duration, instead of once. (this shouldn't really matter, because only a pure calculation should be passed as callback)
- the callback is run initially to kickoff tracking and set the signal's value.
createThrottledMemo
Solid's createMemo
which returned signal is throttled.
How to use it
import { createThrottledMemo } from "@solid-primitives/memo";
const double = createThrottledMemo(prev => count() * 2, 200);
const double = createThrottledMemo(prev => count() * 2, 200, { value: 0 });
Note: the callback is run initially to kickoff tracking and set the signal's value.
createPureReaction
Solid's createReaction
that is based on pure computation (runs before render, and is non-batching)
How to use it
It's usage exactly matches the original. The only difference is in when the callback is being executed, the normal createReaction runs it after render, similar to how effects work, while the createPureReaction is more like createComputed.
import { createPureReaction } from "@solid-primitives/memo"
const [count, setCount] = createSignal(0);
const track = createPureReaction(() => {...});
track(count);
setCount(1);
setCount(2);
Definition
function createPureReaction(onInvalidate: Fn, options?: EffectOptions): (tracking: Fn) => void;
createMemoCache
Custom, lazily-evaluated, cached memo. The caching is based on a key
, it has to be declared up-front as a reactive source, or passed to the signal access function.
how to use it
It takes params:
key
a reactive source, that will serve as cache key (later value access for the same key will be taken from cache instead of recalculated)calc
calculation function returning value to cache. the function is tracking - will recalculate when the accessed signals change.options
set maximum size of the cache, or memo options.
Returns a signal access function.
Import
import { createMemoCache } from "@solid-primitives/memo";
Setting the key up-front as a reactive source
const [count, setCount] = createSignal(1);
const double = createMemoCache(count, n => n * 2);
double();
Provide the key by passing it to the access function
let's accessing different keys in different places
const [count, setCount] = createSignal(1);
const double = createMemoCache((n: number) => n * 2);
double(count());
Calculation function is reactive
will recalculate when the accessed signals change.
const [number, setNumber] = createSignal(1);
const [divisor, setDivisor] = createSignal(1);
const result = createMemoCache(number, n / divisor());
Definition
function createMemoCache<Key, Value>(
key: Accessor<Key>,
calc: CacheCalculation<Key, Value>,
options?: CacheOptions<Value>
): Accessor<Value>;
function createMemoCache<Key, Value>(
calc: CacheCalculation<Key, Value>,
options?: CacheOptions<Value>
): CacheKeyAccessor<Key, Value>;
type CacheCalculation<Key, Value> = (key: Key, prev: Value | undefined) => Value;
type CacheKeyAccessor<Key, Value> = (key: Key) => Value;
type CacheOptions<Value> = MemoOptions<Value> & { size?: number };
Changelog
Expand Changelog
0.0.100
Initial release as a Stage-1 primitive.
0.0.200
Add createWritableMemo
. rename createCache
to createMemoCache
.