On This Page
Signal Options
To provide more granular control over reactivity, Semantic provides several options which let you control how values are updated and compared.
The default options are designed to permit some minor performance overhead as a tradeoff for improved developer experience, but this might not fit all use-cases for Signals.
Signal options are passed as the second argument to signal().
Equality Comparison
By default, Signals use a deep equality comparison, isEqual, to determine if a new value is actually different from the current value. This prevents Reactions from rerunning if the updated value has not changed.
import { signal } from '@semantic-ui/reactivity';
const person = signal({ name: 'John', age: 30 });
// No reactive update triggered (objects are deep equal)person.set({ name: 'John', age: 30 });
// Reactive update triggered (objects differ)person.set({ name: 'Jane', age: 30 });Custom Equality Function
You can provide a custom equality comparison function using the equality option to modify how equality checks are performed. This can potentially speed up comparisons at the cost of potential additional reactivity.
When To Use Custom equality functions can be useful for extremely large objects or data structures where you want to avoid checking their values each time they are accessed.
const customEquality = (a, b) => { // Custom comparison logic (e.g., shallow compare, reference compare) return a === b; // Example: strict reference equality};
// Signal using custom equality checkconst customVar = signal(initialValue, { equality: customEquality });Safety
The safety option controls how a signal guards its stored value against outside mutation.
| Preset | Stores | On get().x = y | Dedupe |
|---|---|---|---|
reference (default) | the value by reference | mutates the signal silently | isEqual |
clone | a defensive copy | mutates the copy, not the signal | isEqual |
none | the value by reference | mutates silently | never |
reference
The default. The signal stores and returns your value as-is, with no copying. It is the fast path and the right choice for most signals, including objects you own and update through set() or the mutation helpers.
const user = signal({ name: 'Alice' });clone
Stores and returns defensive copies, so outside code holding a reference cannot mutate the signal’s value. Reach for it when state might be changed behind your back. Copies use a deep clone by default; pass a clone function to override it.
const config = signal({ theme: 'dark' }, { safety: 'clone' });
const jsonClone = (value) => JSON.parse(JSON.stringify(value));const data = signal({ n: 1 }, { safety: 'clone', clone: jsonClone });none
Stores by reference like reference, but skips the equality check, so every set() notifies even when the value is unchanged. Use it for event-stream signals where each emission matters.
const pulse = signal(null, { safety: 'none' });
pulse.set({ type: 'heartbeat' });pulse.set({ type: 'heartbeat' }); // still notifies