Skip to content

Solid.js Effects — Running Side Effects Reactively

DodaTech Updated 2026-06-28 3 min read

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

  1. Writing to signals inside effects: Writing to a signal inside an effect can cause infinite loops. Use createMemo for derived values.
  2. Forgetting cleanup for subscriptions: Without cleanup, each effect re-run creates a new subscription, leaking resources.
  3. Reading signals without tracking: Signals read outside a tracking scope don't trigger effect re-runs.
  4. Nesting effects unnecessarily: One effect can track multiple signals. Don't split into multiple effects unless cleanup differs.
  5. Assuming effects run synchronously: Effects run after the current synchronous batch completes, not immediately.

Practice Questions

  1. When does an effect run? Answer: Immediately on creation and whenever any signal read inside it changes.

  2. How does Solid.js know which signals an effect depends on? Answer: Automatic dependency tracking. Signals read during effect execution are tracked as dependencies.

  3. 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.

  4. 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

Can I have effects without dependencies?

: Yes. An effect that reads no signals runs once and never re-runs.

How do I manually trigger an effect?

: Effects re-run automatically when dependencies change. Use a dummy signal that you increment to force re-run.

Can effects be async?

: Yes, but the cleanup function must be synchronous. Handle async cleanup separately.

What's the difference between createEffect and createMemo?

: Effects run for side effects and don't return values. Memos return computed values that other reactive primitives can read.

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