Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Effects: createEffect, onMount, onCleanup

An effect is code that does not build markup but does something "outside": writes to localStorage, changes the tab title, starts a timer. Solid runs an effect after rendering and repeats it when the signals it read change.

createEffect

// src/components/Counter.jsx
import { createSignal, createEffect } from 'solid-js';
 
export default function Counter() {
  const [count, setCount] = createSignal(0);
 
  createEffect(() => {
    document.title = `Done: ${count()}`;
  });
 
  return <button onClick={() => setCount(count() + 1)}>Mark done</button>;
}

The browser tab title changes on every click. No dependency list is needed as in React's useEffect: Solid sees for itself that the effect read count().

Saving tasks

An effect is handy for keeping the task list between page reloads:

// src/App.jsx
import { createSignal, createEffect } from 'solid-js';
 
export default function App() {
  const saved = JSON.parse(localStorage.getItem('todos') ?? '[]');
  const [todos, setTodos] = createSignal(saved);
 
  createEffect(() => {
    localStorage.setItem('todos', JSON.stringify(todos()));
  });
 
  const add = () => setTodos([...todos(), { id: Date.now(), title: 'Task', done: false }]);
 
  return <button onClick={add}>Add ({todos().length})</button>;
}

Click a few times, then reload the page — the number on the button stays.

onMount

onMount runs once, when the component's markup is already in the page:

// src/components/Clock.jsx
import { createSignal, onMount, onCleanup } from 'solid-js';
 
export default function Clock() {
  const [time, setTime] = createSignal(new Date().toLocaleTimeString());
 
  onMount(() => {
    const timer = setInterval(() => setTime(new Date().toLocaleTimeString()), 1000);
    onCleanup(() => clearInterval(timer));
  });
 
  return <p>It is {time()}</p>;
}

The time on the page updates every second.

onCleanup

onCleanup registers a function that runs when the component is removed from the page or the effect runs again. In the example above it stops the timer; otherwise the timer would keep running after Clock is gone.

FunctionWhen it runs
createEffect(fn)After rendering and after every change of the signals it read
onMount(fn)Once, after insertion into the page
onCleanup(fn)When the component is removed or before the effect reruns

Common mistake

Changing, inside an effect, the same signal the effect reads:

// src/components/Counter.jsx
import { createSignal, createEffect } from 'solid-js';
 
export default function Counter() {
  const [count, setCount] = createSignal(0);
 
  // Wrong: the effect triggers itself again and again
  createEffect(() => setCount(count() + 1));
 
  return <p>{count()}</p>;
}

The effect loops. If a value is computed from other signals, use a derived function or createMemo, and keep effects for working with the outside world.

Thanks for reading!

Donate to the site — we work hard for you.