Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Derived values and createMemo

A derived value is something computed from other data: the number of unfinished tasks, a filtered list, a full name from first and last names. There is no need to store it in a separate signal — it is enough to describe how to get it.

A derived function

The simplest way is an ordinary arrow function that reads signals:

// src/components/Counter.jsx
import { createSignal } from 'solid-js';
 
export default function Counter() {
  const [count, setCount] = createSignal(0);
  const doubled = () => count() * 2;
 
  return (
    <div>
      <p>Tasks: {count()}, doubled: {doubled()}</p>
      <button onClick={() => setCount(count() + 1)}>Add</button>
    </div>
  );
}

On each click both numbers update. doubled is a function, so, like a signal, it is called: doubled(). The call inside JSX reads count(), and Solid tracks that dependency.

createMemo

A derived function runs every time it is called. If the calculation is heavy or the result is used in many places, cache it with createMemo:

// src/components/TodoStats.jsx
import { createSignal, createMemo } from 'solid-js';
 
export default function TodoStats() {
  const [todos, setTodos] = createSignal([
    { id: 1, title: 'Buy milk', done: true },
    { id: 2, title: 'Call Oleg', done: false },
  ]);
 
  const left = createMemo(() => todos().filter((t) => !t.done).length);
 
  const add = () => {
    setTodos([...todos(), { id: Date.now(), title: 'New task', done: false }]);
  };
 
  return (
    <div>
      <p>Left: {left()}</p>
      <p>Total: {todos().length}</p>
      <button onClick={add}>Add</button>
    </div>
  );
}

The page shows "Left: 1" and "Total: 2"; each click increases both numbers. createMemo recomputes the filter only when todos changes, and between changes it returns the saved result.

Which to choose

ApproachWhen it fits
const x = () => ...A simple calculation used in one or two places
createMemo(() => ...)A heavy calculation or many readers

Start with a function. Switch to createMemo when you see the same thing being computed many times.

A memo also returns a function

The result of createMemo is read by calling it, like a signal: left(). You can pass it into props and use it inside other memos — the dependencies chain up automatically.

Common mistake

Duplicating a derived value in a separate signal and updating it by hand:

// src/components/TodoStats.jsx
import { createSignal, createEffect } from 'solid-js';
 
export default function TodoStats() {
  const [todos, setTodos] = createSignal([]);
  // Unnecessary: a second signal and an effect to sync it
  const [total, setTotal] = createSignal(0);
  createEffect(() => setTotal(todos().length));
 
  return <p>Total: {total()}</p>;
}

This code is more complex and can show a stale value. const total = () => todos().length is enough.

Thanks for reading!

Donate to the site — we work hard for you.