
Security News
/Research
Popular node-ipc npm Package Infected with Credential Stealer
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.
@solid-primitives/memo
Advanced tools
Collection of custom memo primitives. They extend Solid's createMemo functionality while keeping the usage similar.
Collection of custom createMemo primitives. They extend it's functionality while keeping the usage similar.
createLatest - A combined memo of a list of sources, returns the value of last updated one.createLatestMany - A combined memo of a list of sources, returns the value of all last updated ones.createWritableMemo - Solid's createMemo which value can be overwritten by a setter.createLazyMemo - Lazily evaluated memo. Will run the calculation only if is being listened to.createPureReaction - A createReaction that runs before render (non-batching).createMemoCache - Custom, lazily-evaluated, memo, with caching based on keys.createReducer - Primitive for updating signal in a predictable way.npm install @solid-primitives/memo
# or
pnpm add @solid-primitives/memo
# or
yarn add @solid-primitives/memo
createLatestA combined memo of multiple sources, last updated source will be the value of the returned signal.
createLatest takes two arguments:
sources - list of reactive calculations/signals/memosoptions - memo optionsAnd returns a signal with value of the last change
import { createLatest } from "@solid-primitives/memo";
const [count, setCount] = createSignal(1);
const [text, setText] = createSignal("hello");
const lastUpdated = createLatest([count, text]);
lastUpdated(); // => "hello"
setCount(4);
lastUpdated(); // => 4
createLatestManyA combined memo of multiple sources, returns the values of sources updated in the last tick.
createLatestMany takes two arguments:
sources - list of reactive calculations/signals/memosoptions - memo optionsAnd returns a signal with value of the last updated sources
import { createLatestMany } from "@solid-primitives/memo";
const [count, setCount] = createSignal(1);
const [text, setText] = createSignal("hello");
const lastUpdated = createLatestMany([count, text]);
lastUpdated(); // => [1, "hello"]
setCount(4);
lastUpdated(); // => [4]
createWritableMemoSolid's createMemo which value can be overwritten by a setter.
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.
import { createWritableMemo } from "@solid-primitives/memo";
const [count, setCount] = createSignal(1);
const [result, setResult] = createWritableMemo(() => count() * 2);
result(); // => 2
setResult(5); // overwrites calculation result
result(); // => 5
Using createWritableMemo will let you create a signal from a prop, that can be overwritten by a setter. This is useful for creating a signal from a prop, that can be used in a child component, but also be overwritten by a parent.
const Child: Component<{ selectedId: string }> = props => {
const [selectedId, setSelectedId] = createWritableMemo(() => props.selectedId);
return (
<div>
<div>Selected id: {selectedId()}</div>
<button onClick={() => setSelectedId("1")}>Select 1</button>
<button onClick={() => setSelectedId("2")}>Select 2</button>
</div>
);
};
createLazyMemoLazily evaluated createMemo. Will run the calculation only if is being listened to.
It may be useful for memos that aren't being listened to all the time, to reduce performance cost of wastefull computations.
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";
// use like a createMemo
const double = createLazyMemo(() => count() * 2);
double(); // T: number
Set the initial value, or type of the previous value in calculation function will be T | undefined.
// set the initial value
const memo = createLazyMemo(prev => count() + prev, 123);
memo(); // T: number
equalsThe lazy memo, as it is implemented now, doesn't allow for setting a equals function like you could with normal memo. It is always set to equals: false as a lazy memo cannot eagerly evaluate to check if the next value is the same as the previous, it needs to always notify it's observers so they can read from it and evaluate the memo.
Lazy memos in Solid 2.0 will be ownerless — the reactive context of the callback will depend of the place of read, not creation.
This implementation will always execute it's callback with the context of owner it was created under. So ti won't work with Suspense the way you might expect — meaning that it won't activate any Suspense that is below place of creation.
Although if you only need the ownerless characteristics so that the memo can be garbage-collected when not referenced, instead of waiting for owner cleanup, you can wrap it with runWithOwner to create it without an owner:
const memo = runWithOwner(null, () => {
return createLazyMemo(() => /* ... */)
})
There are very few actual good applications of a lazy memo, that couldn't be solved with other means — like improving the data architecture. For example, you can always only create memos in places that you intend to use it in, instead of declaring it prematurely.
// instead of memo, distribute only a calculation function
const getDouble = (n: number) => n * 2;
// and only declare memo where you want to use it
const double = createMemo(() => getDouble(count()));
https://codesandbox.io/s/solid-primitives-memo-demo-3w0oz?file=/index.tsx
createDebouncedMemocreateDebouncedMemo is deprecated. Please use createSchedule from @solid-primitives/schedule instead.
import { createSchedule, debounce } from "@solid-primitives/schedule";
const scheduled = createScheduled(fn => debounce(fn, 200));
const double = createMemo(p => {
const value = count();
return scheduled() ? value * 2 : p;
}, 0);
createThrottledMemocreateThrottledMemo is deprecated. Please use createSchedule from @solid-primitives/schedule instead.
import { createSchedule, throttle } from "@solid-primitives/schedule";
const scheduled = createScheduled(fn => throttle(fn, 200));
const double = createMemo(p => {
const value = count();
return scheduled() ? value * 2 : p;
}, 0);
createPureReactionSolid's createReaction that is based on pure computation (runs before render, and is non-batching)
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); // triggers callback
// sources need to be re-tracked every time
setCount(2); // doesn't trigger callback
function createPureReaction(onInvalidate: Fn, options?: EffectOptions): (tracking: Fn) => void;
createMemoCacheCustom, 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.
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 { createMemoCache } from "@solid-primitives/memo";
const [count, setCount] = createSignal(1);
const double = createMemoCache(count, n => n * 2);
// access value:
double();
let's accessing different keys in different places
const [count, setCount] = createSignal(1);
const double = createMemoCache((n: number) => n * 2);
// access value with key:
double(count());
will recalculate when the accessed signals change.
// changing number creates new entry in cache
const [number, setNumber] = createSignal(1);
// changing divisor will force cache to be recalculated
const [divisor, setDivisor] = createSignal(1);
// calculation subscribes to divisor signal
const result = createMemoCache(number, n / divisor());
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 };
createReducerPrimitive for updating signal in a predictable way. SolidJS equivalent of React's useReducer.
createReducer is useful for:
sets of a signalfunction createReducer<T, ActionData extends any[]>(
dispatcher: (state: T, ...args: ActionData) => T,
initialValue: T,
options?: SignalOptions<T>,
): [accessor: Accessor<T>, dispatch: (...args: ActionData) => void];
dispatcher is the reducer, it's 1st parameter always is the current state of the reducer and it returns the new state of the reducer.
accessor can be used as you use a normal signal: accessor(). It contains the state of the reducer.
dispatch is the action of the reducer, it is a sort of setSignal that does NOT receive the new state, but instructions to create it from the current state.
For example:
import { createReducer } from "@solid-primitives/memo";
function Counter() {
const [count, double] = createReducer(c => c * 2, 1);
return <button onClick={double}>{count()}</button>;
}
The reducer also can receive other arguments:
import { createReducer } from "@solid-primitives/memo";
const dispatcher = (c: number, type: "double" | "increment") => {
if (type == "double") {
return c * 2;
} else {
return c + 1;
}
};
function Counter() {
const [count, handleClick] = createReducer(dispatcher, 1);
return (
<div>
<span>{count()}</span>
<button onClick={() => handleClick("double")}>Double</button>
<button onClick={() => handleClick("increment")}>Increment</button>
</div>
);
}
React allows a 3rd argument:
const fib = (n: number) => (n < 2 ? n : fib(n - 1) + fib(n - 2));
const nextFib = (n: number) => Math.round((n * (1 + sqrt(5))) / 2);
const [fibonacci, nextFibonacci] = useReducer(nextFib, 1, fib);
You need to convert that to the following format:
const [fibonacci, nextFibonacci] = createReducer(nextFib, fib(1));
https://codesandbox.io/s/solid-primitives-reducer-demo-7nrfs2?file=/index.tsx
See CHANGELOG.md
FAQs
Collection of custom memo primitives. They extend Solid's createMemo functionality while keeping the usage similar.
The npm package @solid-primitives/memo receives a total of 15,371 weekly downloads. As such, @solid-primitives/memo popularity was classified as popular.
We found that @solid-primitives/memo demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
/Research
Socket detected malicious node-ipc versions with obfuscated stealer/backdoor behavior in a developing npm supply chain attack.

Security News
TeamPCP and BreachForums are promoting a Shai-Hulud supply chain attack contest with a $1,000 prize for the biggest package compromise.

Security News
Packagist urges PHP projects to update Composer after a GitHub token format change exposed some GitHub Actions tokens in CI logs.