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

@spearwolf/signalize

v0.13.0

Published

signals and effects for all

Downloads

108

Readme

@spearwolf/signalize

signals and effects for all ❗

signalize hero image


npm (scoped) GitHub Workflow Status (with event) GitHub

@spearwolf/signalize is a javascript library for creating signals and effects.

  • a standalone javascript library that is framework agnostic
  • without side-effects and targets ES2022 based environments
  • written in typescript v5 and uses the new tc39 decorators :rocket:
  • however, it is optional and not necessary to use the decorators

⚙️ Install

npm install @spearwolf/signalize

Packaged as ES2022 and exported as unbundled ESM-only javascript modules. Type definitions and source maps also included.

🔎 Since v0.5 there is also a CHANGELOG

Since v0.7 commonjs modules are no longer exported ❗

Overview 👀

The whole API of @spearwolf/signalize is about ..

  • signals
    • like state variables with hidden superpowers
    • when the value of a signal changes, all subscribers are automatically informed
  • effects
    • are callback functions that are automatically executed when one or more signals — which are read within the effect function — change
    • just think of it as a standalone useEffect() hook (but without react :wink:)
  • connections
    • which are basically links between signals and functions
    • like the geometry node connections in blender or the node connections in blueprints of the unreal engine

A functional API is provided, as well as a class-based API that uses decorators.

🔎 Under the hood the event-driven library @spearwolf/eventize is used!

📖 Usage

⚠️ While the library / API is already quite stable and almost completely tested, this documentation is still in an early state ... if you want to get an exact picture of the functionality of the library, you currently have no choice but to inspect the tests and the source code! You are welcome to ask directly/start a discussion if you want :)

see CHEATSHEET for a quick overview of the API

Create Signals

Signals are mutable states that can trigger effects when changed.

Create Effects

Effects are functions that react to changes in signals and are executed automatically.

Without effects, signals are nothing more than ordinary variables.

With effects, you can easily control behavior changes in your application without having to write complex dependency or monitoring logic.

Effects are always executed the first time and automatically immediately if a signal that is read out within the effect is changed afterwards.

Sometimes, however, this is a little more often than you actually need: If you change a and then b in the example above, the result will be announced by the effect each time. If you only want to get the final result after changing both signals, you can use the batch(callback) function.

The full signature of createEffect

The createEffect() API returns an array with two functions:

const [run, destroy] = createEffect(myEffectCallback);

Optionally you can specify an options object as a parameter:

const [run, destroy] = createEffect(myEffectCallback, { autorun: true });

In which order the options and the effect callback are passed doesn't really matter. both variants are ok ..

const [run, destroy] = createEffect({ autorun: false }, myEffectCallback);

(currently autorun is the only supported option and is true by default)

The run function

With the run function you can call the effect directly. Normally you don't need to do this yourself, because it happens automatically.

In combination with the autorun: false option — which prevents the effect from being called automatically — you can specify exactly the right time for the effect to be executed. This is useful if you want it to happen in a setInterval() or requestAnimationFrame(), for example.

The destroy function

... is quickly explained: if you don't want to use the effect anymore, you can simply remove it by calling the destroy function (if there is a cleanup function, then of course it will be called finally)

The effect callback can optionally return a cleanup function

Your effect callback (which is your function that you pass to the effect as parameter) may also optionally return a cleanup function.

Before calling an effect callback, a previously returned cleanup function (if you provided it) is executed.

🔎 Does this behaviour look familiar? probably because this feature was inspired by react's useEffect hook

An example of using a cleanup function

const [getSelector, makeInteractive] = createSignal();

function onClick(event) {
  console.log('click! selector=', getSelector(), 'element=', event.target);
}

createEffect(() => {
  if (getSelector()) {
    const el = document.querySelector(getSelector());

    el.addEventListener('click', onClick, false);

    return () => {
      el.removeEventListener('click', onClick, false);
    };
  }
})

makeInteractive('#foo');  // foo is now interactive
makeInteractive('.bar');  // bar is now interactive, but foo is not

Batching

Within the batch callback, all signals are written, but the dependent effects are deferred until the end of the batch function:

See The difference between the standard behavior of effects and the use of batching for more informations on this.

Create Memos

When an effect is created, the effect callback is executed immediately (and then automatically when the values of the dependent signals change).

A memo, on the other hand, allows you to explicitly control when the callback is executed. The memo also returns a result.

On the first call the memo callback is always executed, on subsequent calls the callback is only executed if the dependent signals have changed in the meantime. if not, the previous cached result value is returned.

| ‼️ The memo callback fullName() is executed only on the first call, after that only if one or both signals have changed.


more docs coming!!