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

reactor-lib

v2.3.3

Published

Simple reactive variables. Automatically run functions when variables change.

Downloads

5

Readme

Reactor

Reactor is a library that allows you to write functions that automatically respond to variable changes within them. This allows you to think of your project as a single, static state instead of the constantly changing mess inherent to large projects. Stop tracking changes to your variables and start writing beautiful, intuitive code.

Installation

Node

$ npm install reactor-lib
var Reactor = require('reactor-lib');

Browser

<script src="path/to/reactor.js"></script>

Quick Start

The following example will:

  1. Create a Reactor with a default value
  2. Run a function that retrieves and logs its value
  3. Change the value of the Reactor which will automatically run the previous function
var my_name = new Reactor('Sammy');

Reactor(function() {
	console.log(my_name());
});

my_name('Bobby');

Output:

Sammy
Bobby

Slow Start

Creating Reactors

Reactors are created using new Reactor([default_value]). They can hold values and can optionally be initialized with a default value.

var my_name = new Reactor();
var my_age  = new Reactor(24);

my_name('Sammy');

console.log(my_name());
console.log(my_age());

Output:

Sammy
24

NOTE: You must use the new keyword when creating a Reactor

Creating Reactor Functions

Reactor Functions are creating using Reactor(function, [context]). This runs the function immediately. Within the passed in function, if a Reactor's value is retrieved, the function is registered as dependent on that value and will be re-run when the value changes.

Reactor Functions can contain any number of Reactors. Conversely, Reactors can be used within any number of Reactor Functions.

// This function is dependent on my_name and my_age
Reactor(function() {
	var name = my_name();
	var age  = my_age();

	console.log(name + ' ' + age);
});

// This function is also dependent on my_name and my_age
Reactor(function() {
	my_age();

	console.log('Hello, ' + my_name());
});

NOTE: Do not use the new keyword when creating a Reactor Function

Triggering a Reaction

Any time a Reactor's value is changed, all functions dependent on it will be re-run. This is called a reaction. A reaction only occurs if the new value fails a strict equality comparison with the previous value. A reaction can also be triggered without changing the value by calling <Reactor>.trigger().

// Implicitly trigger a reaction by setting the Reactor's value
my_name('Bobby');

// Explicity trigger a reaction by calling trigger()
my_age.trigger();

Be careful when dealing with objects and arrays. Modifying a property on an object/array is not detected as a change. If you want to force a reaction after modifying an object/array's properties, use the <Reactor>.trigger() method.

var options    = {};
var my_options = new Reactor(options);

options.foo = true;

// This does not trigger a reaction because the Reactor already stores a reference to options
my_options(options);

// This triggers a reaction regardless of the value
my_options.trigger();

// This triggers a reaction because a different object is being set
my_options({foo : true});

Reactors without values

Reactors do not need to have values. In some cases, it's useful to have a Reactor whose sole purpose is to activate Reactor Functions explicitly (similar to the pub/sub pattern).

Because they hold no values, use <Reactor>.trigger() to trigger a reaction.

var generate_random_number = new Reactor();

Reactor(function() {
	// Registers generate_random_number as a dependency
	generate_random_number();

	console.log(Math.random());
});

// Triggers a reaction
generate_random_number.trigger();

Reaction timing and order

When a reaction is triggered, it is not executed immediately. Instead, it is scheduled for the next time the client is idle (typically a few milliseconds). This is to avoid recursion and to aggregrate rapid changes to multiple Reactors in a single reaction.

For simplicity, the order in which Reactor Functions are executed in a reaction is arbitrary. This is because the order of multiple Reactor Functions with shared Reactor dependencies becomes confusing, unpredictable, and not very useful in practical situations. Your Reactor Functions should be isolated units capable of being called at any time in any order.

Examples

Linking a Reactor to an input

var name       = new Reactor('Sammy');
var name_input = document.getElementById('name-input');

Reactor(function() {
	name_input.value = name.value();
});

name_input.addEventListener('change', function() {
	name(this.value);
});

Rendering a Handlebars template

var template  = Handlebars.compile(user_info_template);
var container = document.getElementById('user-info-container');

Reactor(function() {
	container.innerHTML = template({
		first_name : first_name(),
		last_name  : last_name(),
	});
});

API

Reactor(function, [context])

Runs a function with an optional context. If a Reactor's value is retrieved within the function, the function is registered as dependent on the Reactor and will be re-run if a reaction is triggered.

new Reactor([default_value])

Creates a new Reactor with an optional default value

<Reactor>()

Returns the value of a Reactor

<Reactor>(value)

Sets the value of a Reactor. If the value is not strictly equal to the previous value, a reaction is scheduled.

<Reactor>.trigger()

Triggers a reaction without setting the Reactor's value