npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rmemo

v0.51.32

Published

ctx-core rmemo

Downloads

786

Readme

rmemo (Reactive Memo)

rmemo is a tiny no-fluff reactive state management library. The primitive is a reactive memo. A reactive signal is a reactive memo that has a public .set function. rmemo includes memosig, lock_memosig, & a rich api for your reactive state management needs. Features include:

  • memo_
  • signal_
  • memosig_
  • lock_memosig_
  • general purpose contexts with ctx-core/be
  • autosubscriptions
  • async support
  • a terse & focused api
  • performance
  • integration with garbage collector via WeakRef

| imports | size | |------------------------------------------------------------|:-----:| | memo_ | 358 B | | memo_ + sig_ | 381 B | | memo_ + sig_ + be_ + ctx_ | 476 B | | memo_ + sig_ + be_ + ctx_ + be_memo_pair_ + be_sig_triple_ | 559 B |

installation

npm i ctx-core
# or
npm i rmemo

rmemo is part of the ctx-core package. Importing ctx-core/rmemo will enable usage of rmemo. There is also a standalone rmemo package.

usage

// users.ts
import { sig_ } from 'rmemo' // or 'ctx-core/rmemo'
export const user_a$ = sig_<User[]>([], [
  user_a$=>
    fetch('https://my.api/users')
      .then(res=>res.json())
      .then(user_a=>user_a$.set(user_a))
      // Make sure async errors are handled
      .catch(err=>console.error(err))
])
export function user__add(user:User) {
  user_a$.set([...user_a$(), user])
}
export interface User {
  id:number
  name:string
}
// admins.ts
import { memo_ } from 'rmemo' // or 'ctx-core/rmemo'
import { user_a$ } from './users.js'
export const admin_a$ = memo_(()=>user_a$().filter(i=>i.isAdmin))

integration with relementjs

rmemo provides optional opt-in reactivity to relementjs. Gives reativity to Element rendering, Element attributes/props rendering.

how is rmemo different?

rmemo is a small & focused library. memo_ is like nanostore's computed, svelte's derived, solidjs' createMemo, & VanJS' derive. & sig_ is like nanostore's atom, svelte's writable, solidjs' createSignal, & VanJS' state.

| | rmemo | nanostores | solidjs | sveltejs | vanjs | |-------------------------------------------------------|:---------:|:----------------:|:------------------:|:------------------:|:---------:| | small payload | ✅ | ✅ | ✅ | ✅ | ✅ | | performant | ✅ | ✅ | ✅ | ✅ | ✅ | | autosubscriptions | ✅ | ❌ | ✅ | ❌ | ✅ | | server side reactivity | ✅ | ✅ | ✅ | ✅ | ❌ | | diamond dependencies | ✅ | ✅ | ✅ | ✅ | ❌ | | independent from component tree | ✅ | ✅ | ❌ (next version) | ✅ | ✅ | | reactive async | ✅ | ❌ (next version) | ✅ | ✅ | ❌ | | terse api | ✅ | ❌ | ❌ | ❌ | ✅ | | contexts | ✅ | ❌ (next version) | ✅ (component tree) | ✅ (component tree) | ❌ | | Automatic Garbage Collection of derived reactives | ✅ | ❌ | ✅ | ❌ | ✅ |

ctx-core is a general purpose context library. ctx-core's context functions (be_ & ctx__new) are compatible with any state management library. rmemo exports the ctx-core/be package.

advanced rmemos

| function | description | |---------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | memosig_ | A memo signal & a settable memo. Changes to the parent memo resets the memosig, even after setting the memosig._ prop. | | lock_memosig_ | A memo signal & a settable memo. Changes to the parent memo only resets the memosig when if the lock_memosig._ setter was not set. If the lock_memosig._ setter was set, then changes to the parent memo do not reset the lock_memosig. | | be_sig_triple_ | Returns an array of 3 context be_ functions. sig object getter, value getter, & value setter | | id_be_sig_triple_ | Same as be_sig_triple_ + sets the id of the be function | | ns_id_be_sig_triple_ | Same as be_sig_triple_ + sets the id of the be function & operates on the given ctx namespace. | | ns_be_sig_triple_ | Same as be_sig_triple_ & operates on the given ctx namespace. | | be_memo_pair_ | Returns an array of 2 context be_ functions. memo object getter & value getter. | | id_be_memo_pair_ | Same as be_memo_pair_ + sets the id of the be function | | ns_id_be_memo_pair_ | Same as be_memo_pair_ + sets the id of the be function & operates on the given ctx namespace. | | ns_be_memo_pair_ | Same as be_memo_pair_ & operates on the given ctx namespace. | | be_memosig_triple_ | Returns an array of 3 context be_ functions. memosig object getter, value getter, & value setter | | id_be_memosig_triple_ | Same as be_memosig_triple_ + sets the id of the be function | | ns_id_be_memosig_triple_ | Same as be_memosig_triple_ + sets the id of the be function & operates on the given ctx namespace. | | ns_be_memosig_triple_ | Same as be_memosig_triple_ & operates on the given ctx namespace. | | be_lock_memosig_triple_ | Returns an array of 3 context be_ functions. lock_memosig object getter, value getter, & value setter | | id_be_lock_memosig_triple_ | Same as be_lock_memosig_triple_ + sets the id of the be function | | ns_id_be_lock_memosig_triple_ | Same as be_lock_memosig_triple_. Also sets the id of the be function & operates on the given ctx namespace. | | ns_be_lock_memosig_triple_ | Same as be_lock_memosig_triple_ & operates on the given ctx namespace. | | rmemo__wait | Wait for memo to match given condition with a timeout | | rmemo__off | Turn off a memo & remove references to parent memos. Note that the parent memo references the child rmemo using WeakRef. This allows the child memo to not receive updates pending Garbage Collection. | | rmemo__on | Turn on a memo. Re-adds the memo to the WeakRef held by parent memos. | | rmemo__unset | Unset the memo value. Calling the memo again causes the memo to refresh. |

context (ctx)

Contexts are useful for managing state & disposing of state with Garbage Collection. The context holds state. Garbage Collection disposes the state by removing all active references to the ctx.

rmemo includes functions to support contexts using ctx-core. ctx-core uses dependency injection. By passing the ctx as an argument to a function. Most front-end libraries support Context components. These libraries include React, Sveltejs, Solidjs, & others. Assigning the ctx to the Context component give child components access to the ctx.

context example

This example works on the browser side. There is only one instance user_a$ & admin_a$ to render the UI. The server handles concurrent requests. Concurrent requests disallows global or module variables to store request state. So memos stored as module variables is not concurrency safe.

A ctx solves this issue by storing the memo instances in the ctx. Each request instantiates a ctx via ctx_(). A shorted alias to ctx__new().

ctx-core uses the be_ function to define a memoized function to set a "slot" in the ctx.

// users.ts
import { be_, type ctx_T, sig_ } from 'rmemo'
export const user_a$_ = be_(()=>
  sig_<User[]>([], [
    user_a$=>
      fetch('https://an.api/users')
        .then(res=>res.json())
        .then(user_a=>user_a$.set(user_a))
        .catch(err=>console.error(err))
  ]))
export function user__add(ctx:ctx_T, user:User) {
  user_a$_(ctx).set([...user_a$_(ctx)(), user])
}
export interface User {
  id:number
  name:string
}
// admins.ts
import { be_, memo_ } from 'rmemo'
import { user_a$_ } from './users.js'
export const admin_a$_ = be_(ctx=>
  memo_(()=>
    user_a$_(ctx)()
      .filter(i=>i.isAdmin)))

context with helper functions example

Calling user_a$_(ctx)() & admin_a$_(ctx)() is awkward. So rmemo provides some helper functions.

// users.ts
import { be_sig_triple_, type ctx_T } from 'rmemo'
export const [
  user_a$_,
  user_a_,
  user_a__set,
] = be_sig_triple_<User[]>(
  ()=>[], [
    (ctx, user_a$)=>
      fetch('https://an.api/users')
        .then(res=>res.json())
        .then(user_a=>user_a$.set(user_a))
        .catch(err=>console.error(err))
  ])
export function user__add(ctx:ctx_T, user:User) {
  user_a__set(ctx, [...user_a_(ctx), user])
}
export interface User {
  id:number
  name:string
}
// admins.ts
import { be_memo_pair_ } from 'rmemo'
import { type User, user_a_ } from './users.js'
export const [
  admin_a$_,
  admin_a_,
] = be_memo_pair_(ctx=>
  user_a_(ctx)
    .filter(i=>i.isAdmin))

Note about the Tag Vector Name Convention

You may have noticed the usage of underscore casing. And the trailing _ for factory functions. The Tag Vector name system describes these patterns.

motivation

I liked & used some popular reactive state management solutions. These popular libraries include nanostores, solidjs, svelte, & vanJS. I needed a general solution that I can use on the browser & server, with web UIs & domain libraries. For automating builds & deployments. These projects focus on their particular objectives. I found they were unable to support my use cases in one way or another.

An impasse in adding autosubscriptions to nanostores. An impasse in adding server-side reactive support to vanJS. Both led me to create rmemo.

Name Convention

I use the tag vector name system. An app can have many reactive elements defined. Especially when these reactive elements make up the domain model. Tag Vector provides terse & expressive api for these many instances.