Run code automatically when signals change. Built-in cleanup. Simpler than useEffect!
Effects are actions that happen automatically when a signal changes. Like setting up a "watcher" that says "whenever this changes, do that!"
💡 Real-life example: Like a motion sensor light! When it detects movement (signal changes), it automatically turns on the light (effect runs). No manual switch needed!
Because you need to do things WHEN state changes: save to server, log analytics, start timers, etc.
useEffect(() => {
// What dependencies?? 🤔
console.log(count, name);
}, [count, name]); // Easy to forget!
// ↑ Manual tracking = BUGS
// Forgot to add 'name' to array?
// Effect won't run when name changes!useSignalEffect(() => {
// Auto-tracks EVERYTHING! ✨
console.log(count, name);
}); // No dependency array!
// Automatically knows count and name
// are dependencies. No manual work!useSignalEffect(() => {
// Code here runs when ANY signal used inside changes
console.log('Count changed to:', count);
// Optional cleanup (runs before next effect)
return () => {
console.log('Cleaning up!');
};
});useSignalEffect(() => {
localStorage.setItem(
'draft',
draftText
);
});useSignalEffect(() => {
analytics.track(
'page_view',
{ page: currentPage }
);
});useSignalEffect(() => {
const id = setInterval(
() => tick(), 1000
);
return () => clearInterval(id);
});useSignalEffect(() => {
fetch(`/api/${userId}`)
.then(r => r.json())
.then(setUserData);
});Every time you change the counter, the effect logs it automatically ⬇️
const [count, setCount] = useSignal(0);useSignalEffect(() => {
console.log('Count is:', count);
});💡 It auto-tracks that it depends on count - no array needed!
setCount(5); // Effect runs! ✨import { useSignal, useSignalEffect } from 'signalforge/react';
function TimerComponent() {
const [seconds, setSeconds] = useSignal(0);
// Effect runs when seconds changes
useSignalEffect(() => {
console.log(`Timer at: ${seconds} seconds`);
// Optional: Return cleanup function
return () => {
console.log(`Cleaning up timer at ${seconds}`);
};
});
// Another effect - can have multiple!
useSignalEffect(() => {
if (seconds >= 10) {
alert('Timer reached 10 seconds!');
}
});
return (
<div>
<h2>{seconds} seconds</h2>
<button onClick={() => setSeconds(seconds + 1)}>
Add Second
</button>
</div>
);
}
// ✨ No dependency array needed!
// ✨ Auto-tracks what you use
// ✨ Cleanup runs before next effectuseSignalEffect(() => {
fetchUser(userId);
});useSignalEffect(() => {
analytics.track(page);
});useSignalEffect(() => {
const id = setInterval(fn, 1000);
return () => clearInterval(id);
});useSignalEffect(() => {
localStorage.setItem('user', JSON.stringify(user));
});When your effect returns a function, it gets called before the next effect runs or when the component unmounts.
useSignalEffect(() => {
// 1. Set up resources
const subscription = api.subscribe(userId);
const timer = setInterval(() => {...}, 1000);
// 2. Return cleanup function
return () => {
subscription.unsubscribe(); // Clean up!
clearInterval(timer); // Prevent memory leaks!
};
});Master effects? Try these advanced demos: