Effects
Effects let you run side effects when reactive state changes. Logging, DOM manipulation, API calls—anything that needs to happen because something changed.
Basic Usage
const { signal, effect } = Lightview;
const count = signal(0);
// This runs immediately, then re-runs when count changes
effect(() => {
console.log('Count is now:', count.value);
});
count.value = 1; // Logs: "Count is now: 1"
count.value = 2; // Logs: "Count is now: 2"
Automatic Dependency Tracking
Effects automatically track which signals they read. No need to declare dependencies—Lightview figures it out:
const firstName = signal('Alice');
const lastName = signal('Smith');
const showFull = signal(true);
effect(() => {
if (showFull.value) {
// Tracks firstName, lastName, and showFull
console.log(`${firstName.value} ${lastName.value}`);
} else {
// Only tracks firstName and showFull
console.log(firstName.value);
}
});
Stopping Effects
Effects return a stop function:
const count = signal(0);
const stop = effect(() => {
console.log('Count:', count.value);
});
count.value = 1; // Logs
count.value = 2; // Logs
stop(); // Stop the effect
count.value = 3; // Nothing logged
Common Patterns
Syncing to External Systems
const theme = signal('light');
effect(() => {
document.body.setAttribute('data-theme', theme.value);
});
Local Storage Persistence
const settings = signal(
JSON.parse(localStorage.getItem('settings')) || {}
);
effect(() => {
localStorage.setItem('settings', JSON.stringify(settings.value));
});
API Calls
const userId = signal(1);
const userData = signal(null);
effect(async () => {
const id = userId.value;
const response = await fetch(`/api/users/${id}`);
userData.value = await response.json();
});
Effects vs Computed
| Use Case | Use This |
|---|---|
| Derive a value from signals | computed() |
| Side effects (logging, API calls, DOM) | effect() |
| Value needed in UI | computed() |
| Just need to "do something" | effect() |
const name = signal('World');
const log = signal([]);
effect(() => {
log.value = [...log.value, `Hello, ${name.value}!`].slice(-5);
});
// Change name to see the effect in action