LinkedSignal API¶
reaktiv.LinkedSignal
¶
A writable signal that automatically recomputes when source signals change.
LinkedSignal combines the benefits of computed signals (automatic updates) with writable signals (can be set manually). When source signals change, it recomputes. When manually set, it holds that value until sources change again.
Perfect for form inputs, UI state, and derived values that users can override.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
computation_or_source
|
Union[Callable[[], T], Signal[U], None]
|
The computation function (simple pattern) or source signal |
None
|
source
|
Optional[Union[Signal[U], Callable[[], U]]]
|
Optional source signal or callable (advanced pattern) |
None
|
computation
|
Optional[Callable[[U, Optional[PreviousState[T]]], T]]
|
Optional computation function (advanced pattern) |
None
|
equal
|
Optional[Callable[[T, T], bool]]
|
Optional custom equality function for change detection |
None
|
Examples:
Simple pattern (automatic derivation):
from reaktiv import Signal, LinkedSignal
fahrenheit = Signal(32)
# Celsius automatically computes from Fahrenheit
celsius = LinkedSignal(lambda: (fahrenheit() - 32) * 5/9)
print(celsius()) # 0.0
fahrenheit.set(212)
print(celsius()) # 100.0
# Can override manually
celsius.set(25)
print(celsius()) # 25.0 (manual value)
# Changing source recomputes
fahrenheit.set(68)
print(celsius()) # 20.0 (recomputed from source)
Form input pattern:
from reaktiv import Signal, LinkedSignal, Effect
# Server data
server_name = Signal("John Doe")
# Form input linked to server data
input_value = LinkedSignal(lambda: server_name())
# Track changes (keep reference to prevent GC)
effect = Effect(lambda: print(f"Input: {input_value()}"))
# Prints: "Input: John Doe"
# User edits the input
input_value.set("Jane Smith")
# Prints: "Input: Jane Smith"
# Server data refreshes
server_name.set("John Updated")
# Prints: "Input: John Updated" (reset to server value)
Advanced pattern (with previous state):
from reaktiv import Signal, LinkedSignal, PreviousState
total_pages = Signal(10)
def clamp_page(page_num, prev):
max_page = total_pages()
if max_page == 0:
return None
# First time or source changed - use default
if prev is None or prev.source != max_page:
return 1
# Clamp to valid range
return max(1, min(prev.value, max_page))
current_page = LinkedSignal(
source=total_pages,
computation=clamp_page
)
print(current_page()) # 1 (default)
current_page.set(5)
print(current_page()) # 5
total_pages.set(3)
print(current_page()) # 3 (clamped to max)
As decorator:
from reaktiv import Signal, LinkedSignal
source = Signal(0)
@LinkedSignal
def derived():
return source() * 2
print(derived()) # 0
source.set(5)
print(derived()) # 10
derived.set(100)
print(derived()) # 100 (manual override)