SolidJS
01 / 02

SolidJS Fundamentals: Signals, Effects & Memos

SolidJS: Signals, Effects & Memos

SolidJS is a declarative JSX-based UI library built around fine-grained reactivity rather than a virtual DOM. Unlike React, a Solid component function runs only ONCE during setup -- reactivity happens through signal updates writing directly to specific DOM nodes, not by re-invoking the whole component.

createSignal: Reactive Primitives

import { createSignal } from 'solid-js'

function Counter() {
  const [count, setCount] = createSignal(0)

  return (
    <button onClick={() => setCount(count() + 1)}>
      Count: {count()}
    </button>
  )
}

// count() must be CALLED as a function to read its value -- this is
// what lets Solid track exactly where the signal is being read,
// enabling updates to only the specific DOM node that depends on it

createEffect & createMemo

import { createSignal, createEffect, createMemo } from 'solid-js'

const [count, setCount] = createSignal(0)

// Automatically re-runs whenever count changes -- no manual
// dependency array needed, unlike React's useEffect(fn, [count])
createEffect(() => {
  console.log('count is now', count())
})

// Derived, CACHED value -- only recomputes when count actually
// changes; multiple reads of doubled() share the same computation
const doubled = createMemo(() => count() * 2)

Why Props Shouldn't Be Destructured

// WRONG -- destructuring captures a static snapshot at setup time,
// since the component function only runs once
function Greeting({ name }: { name: string }) {
  return <p>Hello, {name}</p>  // never updates if `name` prop changes
}

// CORRECT -- accessing props.name directly preserves reactivity,
// re-reading the live value each time
function Greeting(props: { name: string }) {
  return <p>Hello, {props.name}</p>
}

Control Flow: Show, For, Switch/Match

import { Show, For, Switch, Match } from 'solid-js'

// Conditional rendering -- a plain `if` at the component-body level
// only evaluates once at setup, so <Show> exists as a reactive
// primitive that correctly toggles as `when` changes over time
<Show when={loggedIn()} fallback={<Login />}>
  <Dashboard user={user()} />
</Show>

// Optimized list rendering -- reuses DOM nodes by item identity,
// rather than a plain .map() which loses fine-grained per-item tracking
<For each={items()}>
  {(item) => <li>{item.name}</li>}
</For>

// Multi-branch conditional
<Switch>
  <Match when={status() === 'loading'}><Spinner /></Match>
  <Match when={status() === 'error'}><ErrorMessage /></Match>
</Switch>

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free