Signal API reference for Signal in Semantic UI's reactivity system box API Reference
Categories

Signal

Signal is the core class for creating signals in Semantic UI’s reactivity system. It allows you to create values that can be observed and will trigger reactions when changed.

Constructor

Creates a new reactive variable with the given initial value.

Syntax

new Signal(initialValue, options);

Parameters

NameTypeDescription
initialValueanyThe initial value of the reactive variable
optionsObject(Optional) Configuration options

Options

NameTypeDefaultDescription
safety'freeze' | 'reference' | 'none''freeze'Value-protection preset. See Signal Options for details.
equalityFunctionFunctionisEqualCustom function to determine if the value has changed
cloneFunctionFunctioncloneCustom function used by signal.clone()

Usage

Basic Usage

import { Signal } from '@semantic-ui/reactivity';
const counter = new Signal(0);

Custom Equality Function

import { Signal } from '@semantic-ui/reactivity';
const person = new Signal({ name: 'John', age: 30 }, {
equalityFunction: (a, b) => a.name === b.name && a.age === b.age
});

Holding Borrowed Data

The default safety: 'freeze' deep-freezes object and array values on set to catch accidental in-place mutation. For signals holding objects you don’t own — anything returned from a library, fetched from an API, or passed through a callback — opt out with safety: 'reference' so the library’s own reference isn’t poisoned.

import { Signal } from '@semantic-ui/reactivity';
const searchResults = new Signal(pagefindResults, { safety: 'reference' });

See the Signals and Foreign References section of the signals guide for the full heuristic.

Get

Returns the current value of the reactive variable.

Syntax

someValue.get();

Alias

value can be used as an alias for get() if preferred

import { Signal } from '@semantic-ui/reactivity';
const counter = new Signal(0);
console.log(counter.value); // Output: 0
counter.value = 1;
console.log(counter.value); // Output: 1

Returns

any - The current value of the reactive variable.

Usage

Retrieving the Current Value

import { Signal } from '@semantic-ui/reactivity';
const counter = new Signal(0);
console.log(counter.get()); // Output: 0

Set

Sets a new value for the reactive variable.

Syntax

someValue.set(newValue);

Parameters

NameTypeDescription
newValueanyThe new value to set

Usage

Setting a New Value

import { Signal } from '@semantic-ui/reactivity';
const counter = new Signal(0);
counter.set(1);
console.log(counter.get()); // Output: 1

Subscribe

Creates a subscription that runs the callback whenever the value changes.

Parameters

NameTypeDescription
callbackFunctionFunction to be called when the value changes

Returns

Object - A subscription object with a stop() method to unsubscribe.

Usage

import { Signal } from '@semantic-ui/reactivity';
const counter = new Signal(0);
const subscription = counter.subscribe((newValue) => {
console.log('Counter changed:', newValue);
});
counter.set(1); // Console: "Counter changed: 1"
subscription.stop(); // Stops the subscription

Depend

Registers this signal as a dependency in the current reactive context without reading or returning the value. This is useful when you want a reaction to re-run when a signal changes, but you don’t need the value itself.

Syntax

someValue.depend();

Usage

Subscribing Without Reading

import { Reaction, Signal } from '@semantic-ui/reactivity';
const theme = new Signal({ mode: 'dark', colors: { /* ... */ } });
// Re-run when theme changes, but use a different source for rendering
Reaction.create(() => {
theme.depend();
console.log('Theme changed, re-rendering...');
});
theme.set({ mode: 'light', colors: { /* ... */ } });

Notify

Force-triggers all subscribers without changing the signal’s value. This bypasses the equality check, making it useful when external code has mutated something and you need to notify dependents.

Syntax

someValue.notify();

Usage

Force-Triggering After External Mutation

import { Reaction, Signal } from '@semantic-ui/reactivity';
const canvas = new Signal(document.createElement('canvas'), { safety: 'reference' });
Reaction.create(() => {
const el = canvas.get();
console.log('Canvas updated');
});
// External code draws on the canvas — the reference hasn't changed
// but dependents need to know about it
canvas.peek().getContext('2d').fillRect(0, 0, 100, 100);
canvas.notify();

hasDependents

Returns whether any reactive contexts are currently subscribed to this signal.

Syntax

someValue.hasDependents();

Returns

boolean - true if at least one reaction depends on this signal.

Usage

import { Reaction, Signal } from '@semantic-ui/reactivity';
const data = new Signal(null);
console.log(data.hasDependents()); // false
const reaction = Reaction.create(() => {
data.get();
});
console.log(data.hasDependents()); // true
reaction.stop();
console.log(data.hasDependents()); // false

Peek

Returns the current value without triggering reactions.

Syntax

someValue.peek();

Returns

any - The current value of the reactive variable.

Usage

import { Signal } from '@semantic-ui/reactivity';
const counter = new Signal(0);
console.log(counter.peek()); // Output: 0

Clear

Sets the value of the reactive variable to undefined and trigger reactions.

Syntax

someValue.clear();

Usage

import { Signal } from '@semantic-ui/reactivity';
const counter = new Signal(0);
counter.clear();
console.log(counter.get()); // Output: undefined

Mutate

Safely mutates the current value using a mutation function. Under safety: 'freeze' the mutation function must return a new value (in-place mutation throws). Under safety: 'reference' or 'none' the function may mutate in place and reactivity still fires.

Syntax

someValue.mutate(mutationFn);

Parameters

NameTypeDescription
mutationFnFunctionA function that receives the current value and either mutates it in place or returns a new value

Returns

The return value of the mutation function, if any.

Usage

Returning a New Value (works under all safety modes)

import { Signal } from '@semantic-ui/reactivity';
const items = new Signal(['apple', 'banana']);
items.mutate(arr => [...arr, 'orange']);
console.log(items.get()); // ['apple', 'banana', 'orange']
const count = new Signal(5);
count.mutate(val => val * 2);
console.log(count.get()); // 10

In-place Mutation (only under safety: ‘reference’ or ‘none’)

import { Signal } from '@semantic-ui/reactivity';
const items = new Signal(['apple', 'banana'], { safety: 'reference' });
items.mutate(arr => {
arr.push('orange'); // Mutate in place — allowed because the value isn't frozen
});
console.log(items.get()); // ['apple', 'banana', 'orange']

With Custom Classes

import { Signal } from '@semantic-ui/reactivity';
class Counter {
constructor(value) {
this.value = value;
}
increment() {
this.value++;
}
}
// Class instances aren't frozen by default (deepFreeze skips them),
// but set safety: 'reference' explicitly when you plan to mutate in place
const counter = new Signal(new Counter(0), {
safety: 'reference',
equalityFunction: (a, b) => a.value === b.value,
});
counter.mutate(c => c.increment());
console.log(counter.get().value); // 1

Derive

Creates a new signal that derives its value from this signal. The derived signal automatically updates when the source signal changes.

Syntax

signal.derive(computeFn, options)

Parameters

NameTypeDescription
computeFnFunctionFunction that receives the current signal value and returns the derived value
optionsObject(Optional) Same configuration options as Signal constructor

Returns

TypeDescription
SignalA new Signal containing the derived value

Usage

Basic Derivation

import { Signal } from '@semantic-ui/reactivity';
const numbers = new Signal([1, 2, 3, 4, 5]);
// Derive the array length
const count = numbers.derive(arr => arr.length);
console.log(count.get()); // 5
// When numbers changes, count updates automatically
numbers.push(6);
console.log(count.get()); // 6

Object Property Extraction

const user = new Signal({ name: 'Alice', age: 30, email: 'alice@example.com' });
// Derive just the display name
const displayName = user.derive(u => u.name.toUpperCase());
console.log(displayName.get()); // "ALICE"

Array Filtering and Transformation

const items = new Signal([
{ id: 1, name: 'Apple', inStock: true },
{ id: 2, name: 'Banana', inStock: false },
{ id: 3, name: 'Orange', inStock: true }
]);
// Derive available items
const availableItems = items.derive(list =>
list.filter(item => item.inStock)
);
console.log(availableItems.get().length); // 2

Signal.computed

Creates a computed signal whose value is calculated from multiple signals. The computed signal recalculates whenever any of its dependencies change.

Syntax

Signal.computed(computeFn, options)

Parameters

NameTypeDescription
computeFnFunctionFunction that accesses other signals and returns the computed value
optionsObject(Optional) Same configuration options as Signal constructor

Returns

TypeDescription
SignalA new Signal containing the computed value

Usage

Basic Computation

import { Signal } from '@semantic-ui/reactivity';
const firstName = new Signal('John');
const lastName = new Signal('Doe');
// Compute full name from multiple signals
const fullName = Signal.computed(() =>
`${firstName.get()} ${lastName.get()}`
);
console.log(fullName.get()); // "John Doe"
// When either signal changes, fullName updates automatically
firstName.set('Jane');
console.log(fullName.get()); // "Jane Doe"

Mathematical Calculations

const quantity = new Signal(3);
const price = new Signal(10.99);
const taxRate = new Signal(0.08);
// Compute total with tax from multiple sources
const total = Signal.computed(() => {
const subtotal = quantity.get() * price.get();
const tax = subtotal * taxRate.get();
return Number((subtotal + tax).toFixed(2));
});
console.log(total.get()); // 35.64

Conditional Logic

const user = new Signal({ role: 'admin', active: true });
const permissions = new Signal(['read', 'write']);
// Compute effective permissions based on multiple factors
const effectivePermissions = Signal.computed(() => {
const currentUser = user.get();
const basePermissions = permissions.get();
if (!currentUser.active) {
return [];
}
if (currentUser.role === 'admin') {
return [...basePermissions, 'delete', 'manage'];
}
return basePermissions;
});
console.log(effectivePermissions.get()); // ["read", "write", "delete", "manage"]
Previous
Reactivity
Next
Reaction