Skip to content

Understanding Effects In SolidJS

Understanding Effects In SolidJS

Understanding Effects In SolidJS

In SolidJS, effects are a fundamental concept that helps developers manage side effects and reactive dependencies within their applications. Unlike standard functions that execute once and are done, effects in SolidJS are designed to automatically re-run whenever their dependencies change. This article will explore what effects are, how to use them, manage dependencies, handle multiple signals, and the lifecycle functions that enhance their functionality.

What Are Effects?

Effects in SolidJS are functions that automatically execute when the signals or reactive values they depend on change. This capability makes effects essential for managing side effects like DOM manipulations, data fetching, and subscriptions.

Creating an Effect

To create an effect in SolidJS, you use the createEffect function. This function takes a callback that runs whenever the effect is triggered by a change in its dependencies.

import { createEffect, createSignal } from "solid-js";

const [isOnline, setIsOnline] = createSignal(false);

createEffect(() => {
  console.log(`User is ${isOnline() ? "online" : "offline"}`);
});

// Simulate changing the user's online status
setIsOnline(true); // Output: User is online

In this example, the effect logs the user’s online status to the console. Each time the isOnline signal changes, the effect re-runs and logs the updated status.

Managing Dependencies

Dependencies in effects are the reactive values or signals that an effect observes. When any of these dependencies change, the effect re-runs. Interestingly, SolidJS automatically tracks these dependencies, meaning you don’t need to manually specify them, which reduces the risk of errors.

When an effect is initialized, it runs once even if its dependencies haven't changed. This initial run is useful for setting up the effect, initializing variables, or subscribing to signals.

createEffect(() => {
  console.log("This effect runs once at initialization");
});

createEffect(() => {
  console.log(isOnline()); // This effect runs every time 'isOnline' changes
});

Subscribing to Signals

When an effect observes a signal, it essentially subscribes to it. This subscription allows the effect to re-run whenever the signal's value changes.

import { createSignal, createEffect } from "solid-js";

const [temperature, setTemperature] = createSignal(25);

createEffect(() => {
  console.log(`Current temperature: ${temperature()}°C`);
});

// Update temperature
setTemperature(30); // Output: Current temperature: 30°C

In this example, the effect logs the current temperature whenever it changes.

Managing Multiple Signals

Effects in SolidJS can observe multiple signals simultaneously. This means that a single effect can track changes in multiple reactive values, re-running whenever any of them change.

import { createSignal, createEffect } from "solid-js";

const [temperature, setTemperature] = createSignal(20);
const [humidity, setHumidity] = createSignal(50);

createEffect(() => {
  console.log(`Temperature: ${temperature()}°C, Humidity: ${humidity()}%`);
});

// Update signals
setTemperature(22); // Output: Temperature: 22°C, Humidity: 50%
setHumidity(55);    // Output: Temperature: 22°C, Humidity: 55%

Here, the effect monitors both temperature and humidity signals. It re-runs when either signal changes, ensuring that it always logs the latest values.

Nested Effects

SolidJS allows effects to be nested within each other. Each nested effect independently tracks its own dependencies, ensuring that changes in an inner effect don’t inadvertently trigger an outer effect.

createEffect(() => {
  console.log("Outer effect runs");

  createEffect(() => {
    console.log("Inner effect runs");
  });

  console.log("Outer effect finishes");
});

In this example, changes to dependencies in the inner effect will not affect the outer effect. This separation prevents unintended behaviors and keeps effects isolated from one another.

Lifecycle Functions

SolidJS offers lifecycle functions that give you more control over when effects are initialized and disposed of. This can include running a side effect only once, or cleaning up a task when it is no longer needed.

onMount

The onMount function is used when you need to run a side effect only once, typically when a component is initialized. Unlike effects, which can re-run multiple times, onMount ensures that the callback is executed only once.

import { onMount } from "solid-js";

function WeatherComponent() {
  const [forecast, setForecast] = createSignal(null);

  onMount(async () => {
    const response = await fetch("https://api.weather.com/forecast");
    setForecast(await response.json());
  });

  return <div>Weather Forecast: {forecast() ? forecast().summary : "Loading..."}</div>;
}

This function is perfect for tasks like fetching data or setting up subscriptions that only need to happen once when the component mounts.

onCleanup

The onCleanup function is used to clean up tasks when a component is unmounted. This is particularly useful for clearing intervals, removing event listeners, or unsubscribing from services, thereby preventing memory leaks.

import { onCleanup } from "solid-js";

function TimerComponent() {
  const [time, setTime] = createSignal(0);

  const interval = setInterval(() => {
    setTime((prev) => prev + 1);
  }, 1000);

  onCleanup(() => {
    clearInterval(interval);
  });

  return <div>Elapsed Time: {time()} seconds</div>;
}

In this example, onCleanup ensures that the interval is cleared when the component is unmounted, preventing it from running indefinitely in the background.

Understanding the Execution Model of Effects in SolidJS

SolidJS introduces a fine-grained reactivity system that sets it apart in the UI development landscape. Unlike React, where effects are tied to component lifecycles and can sometimes trigger unnecessary re-renders, SolidJS operates at a much more granular level. It tracks dependencies down to individual signals or computations, enabling highly efficient updates.

When you create an effect using createEffect, SolidJS automatically monitors every reactive signal accessed within that effect. It builds a precise dependency graph, which maps out exactly which effects should be re-executed when specific signals change. This approach ensures that only the necessary parts of your application update in response to state changes, resulting in more efficient rendering and overall better performance.

Conclusion

Effects in SolidJS are a powerful feature that enable you to react to changes in your application's state dynamically. By leveraging createEffect and using lifecycle functions like onMount and onCleanup, you can create robust and responsive applications. Understanding how to effectively use effects will help you build more efficient, maintainable, and bug-free SolidJS applications.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co