Solid.js Effects — Running Side Effects Reactively
In this tutorial, you will learn about Solid.js Effects. We cover key concepts, practical examples, and best practices to help you master this topic.
Learn Solid.js effects: create reactive side effects with createEffect, track dependencies automatically, and manage cleanup for subscriptions and timers.
In this lesson, you'll use createEffect() to run side effects when signals change, understand automatic dependency tracking, and clean up resources.
What You'll Learn
How to create effects, understand automatic dependency tracking, clean up subscriptions, and avoid common effect pitfalls.
Why It Matters
Effects handle side effects like logging, DOM manipulation, API calls, and integrating with non-reactive libraries. Automatic dependency tracking eliminates manual dependency arrays.
Real-World Use
Doda Browser uses effects to sync tab state with localStorage, update the document title, and log analytics events.
flowchart LR
A[Signal Changes] --> B[Effect Re-runs]
B --> C[Side Effect]
C --> D[Cleanup (optional)]
style B fill:#2c4f7c,color:#fff
Basic Effect
import { createSignal, createEffect } from "solid-js";
const [count, setCount] = createSignal(0);
createEffect(() => {
console.log(`Count changed to: ${count()}`);
});
// Logs: "Count changed to: 0" (runs immediately)
// On click: logs again with new value
Effect with Cleanup
Return a cleanup function for subscriptions:
createEffect(() => {
const id = setInterval(() => {
console.log(`Current count: ${count()}`);
}, 1000);
// Cleanup runs when effect re-runs or component unmounts
return () => clearInterval(id);
});
Tracking Multiple Signals
Effects track all signals read during execution:
const [name, setName] = createSignal("Alice");
const [age, setAge] = createSignal(30);
createEffect(() => {
console.log(`${name()} is ${age()} years old`);
// Re-runs when name or age changes
});
Effect for DOM Manipulation
function VideoPlayer({ src }) {
let videoRef;
const [playing, setPlaying] = createSignal(false);
createEffect(() => {
if (playing()) {
videoRef.play();
} else {
videoRef.pause();
}
});
return (
<div>
<video ref={videoRef} src={src()} />
<button onClick={() => setPlaying(!playing())}>
{playing() ? "Pause" : "Play"}
</button>
</div>
);
}
Common Mistakes
- Writing to signals inside effects: Writing to a signal inside an effect can cause infinite loops. Use
createMemofor derived values. - Forgetting cleanup for subscriptions: Without cleanup, each effect re-run creates a new subscription, leaking resources.
- Reading signals without tracking: Signals read outside a tracking scope don't trigger effect re-runs.
- Nesting effects unnecessarily: One effect can track multiple signals. Don't split into multiple effects unless cleanup differs.
- Assuming effects run synchronously: Effects run after the current synchronous batch completes, not immediately.
Practice Questions
When does an effect run? Answer: Immediately on creation and whenever any signal read inside it changes.
How does Solid.js know which signals an effect depends on? Answer: Automatic dependency tracking. Signals read during effect execution are tracked as dependencies.
What does the effect's return value do? Answer: It's a cleanup function that runs before the effect re-runs or the component unmounts.
Why shouldn't you write to signals inside effects? Answer: Writing to signals inside effects can cause infinite re-execution loops. Use memos for derived values.
Challenge
Build a countdown timer with an effect: create a signal for seconds remaining, use an effect with setInterval to decrement it every second, and stop the timer when it reaches zero.
Mini Project
Create a text editor with auto-save: an effect saves the content to localStorage whenever it changes, debounced by 2 seconds.
FAQ
What's Next
Learn about Solid.js Memos for deriving values from signals with Caching.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro