Effection Logo
@effectionx/signalsv0.1.0thefrontside/effectionx
JSR BadgeNPM Badge with published versionBundle size badgeDependency count badgeTree shaking support badge

Signals

Collection of immutable state containers for primitive data types.

About

One way to think about Effection operation is as composable components of asyncrony. They are conceptually similar to React components in that they're functions that invoke other functions. As with React's component tree, Effection operations are arranged into an operation tree. React components are designed to make it easier to compose DOM where Effection operations are designed to make it easier to compose asynchrony. Because of their simularities, it should come as no surpise that they would share patterns for state management. React Context and Effection Context is one example of this, but the benefits that unidirectional data flow provide to composition is another.

The Flux pattern, in tools like Redux and others, are "classic" ways to implement one directional data from in React applications. Over the years, these patterns involved into Signals which where implemented in variety of UI frameworks. The design of Signals in the JavaScript ecosystem assume that they will be integrated into some UI framework. Effection provides the necessary components to have robust yet simple implementation of Signals that doesn't require a UI framework.

Included in this package

The collection of Signals included in this package rely on Effection's Signal interface to provide immutable value streams with some operations. Each Signal includes set, update and valueOf methods. Each data type also includes methods provided by the primitive version of that data type. For example, ArraySignal provides push and shift, while Set provides difference. We don't implement all methods, mostly because haven't needed all of the methods. If you need a method that we didn't implement but it's available in the promitive type, please create a PR. If you need something else, use the update method.

Boolean Signal

The Boolean Signal provides a stream for a boolean value. You can set the value which will cause the new value to be sent to the stream.

import { each, run, spawn } from "effection";
import { createBooleanSignal } from "@effectionx/signals";

await run(function* () {
  const boolean = yield* createBooleanSignal(true);

  yield* spawn(function* () {
    for (const update of yield* each(boolean)) {
      console.log(update);
      yield* each.next();
    }
  });

  boolean.set(false); // this will send false to the stream
  boolean.set(true); // this will send true to the stream
  boolean.set(true); // this won't send anything since the value hasn't changed
});

For an example of Boolean Signal in action, checkout the faucet

Array Signal

The Array Signal provides a stream for the value of the array. The value is considered immutable - you shouldn't modify the value that comes through the stream, instead invoke methods on the signal to cause a new value to be sent.

import { each, run, spawn } from "effection";
import { createArraySignal } from "@effectionx/signals";

await run(function* () {
  const array = yield* createArraySignal<number>([]);

  yield* spawn(function* () {
    for (const update of yield* each(array)) {
      console.log(update);
      yield* each.next();
    }
  });

  array.push(1, 2, 3); // this will be a single update
});

For an example of Array Signl, checkout the valve and batch stream helpers.

Helpers

is

is helper returns an operation that completes when the value of the stream matches the predicate. It's useful when you want to wait for a signal to enter a specific state. Some of the common use cases are waiting for an array to reach a given length or for a boolean signal to become true or false.

import { run, spawn } from "effection";
import { createBooleanSignal, is } from "@effectionx/signals";

await run(function* () {
  const open = yield* createBooleanSignal(false);

  yield* spawn(function* () {
    yield* is(open, (open) => open === true);
    console.log("floodgates are open!");
  });

  open.set(true);
});

API Reference

interface BooleanSignal extends ValueSignal<boolean>

function createBooleanSignal(): Operation<BooleanSignal>

Parameters

Return Type

Operation<BooleanSignal>

interface ArraySignal<T> extends ValueSignal<T[]>

Interface for return value of createArraySignal.

Type Parameters

T

Methods

push
(item: T): number

Pushes a new value onto the end of the array.

shift
(): Operation<T>

Removes the first value from the array and returns it. If the array is empty, the operation will block until a value is available.

valueOf
(): Readonly<T[]>

Returns the current value of the array.

length
(): number

Returns the length of the array.

function createArraySignal<T>(initial: Iterable<T>): Operation<ArraySignal<T>>

A signal for an immutable array value. The stream emits the current value of the array and new values when the array is updated. The array is immutable and cannot be changed. Instead, the value is replaced with a new value.

Type Parameters

T

Parameters

initial: Iterable<T>

  • The initial value of the signal.

Return Type

Operation<ArraySignal<T>>

A stream of immutable array values.

interface SetSignal<T> extends ValueSignal<Set<T>>

A signal that represents a Set.

Type Parameters

T

Methods

add
(item: T): Set<T>

Adds an item to the Set.

delete
(item: T): boolean

Removes an item from the Set.

difference
(items: Iterable<T>): Set<T>

Returns a new Set with the items that are in the current Set but not in the given iterable.

valueOf
(): Set<T>

Returns the Set value

function createSetSignal<T>(): Operation<SetSignal<T>>

Creates a signal that represents a set. Adding and removing items from the set will push a new value through the stream.

Type Parameters

T

Parameters

  • The initial value of the set.

Return Type

Operation<SetSignal<T>>

A signal that represents a set.

function* is<T>(stream: ValueSignal<T>, predicate: (item: T) => boolean): Operation<void>

Returns an operation that will wait until the value of the stream matches the predicate.

Type Parameters

T

Parameters

stream: ValueSignal<T>

  • The stream to check.

predicate: (item: T) => boolean

  • The predicate to check the value against.

Return Type

Operation<void>

An operation that will wait until the value of the stream matches the predicate.