---
name: solidjs-fine-grained
description: "Build SolidJS apps that out-perform React: signals, stores, resources, suspense — done idiomatically. Writes idiomatic Solid: createSignal, createStore, createResource, suspense + transitions, SolidStart for SSR."
license: MIT
---

# SolidJS Fine-Grained Reactivity

This skill helps you write SolidJS the way it's meant to be written: leaning on its fine-grained reactivity instead of carrying over React habits. It's aimed at developers building Solid or SolidStart apps who want signals, stores, and resources used correctly — without re-rendering whole component trees on every state change.

## When to use it

- Migrating a React mental model to Solid and tripping over the fact that components run once, not on every update.
- Deciding between `createSignal`, `createStore`, and `createMemo` for a piece of state.
- Wiring async data with `createResource` and wrapping it in `<Suspense>` / `<ErrorBoundary>`.
- Setting up SSR, routing, or server functions in a SolidStart project.
- Debugging stale closures, lost reactivity from destructuring props, or effects that fire too often.

## How it works

The skill generates idiomatic Solid and explains the reactive graph behind it. Core primitives it uses correctly:

- **`createSignal`** — the `[get, set]` tuple; reads must happen inside a tracking scope (JSX, `createMemo`, `createEffect`).
- **`createStore`** — proxy-based nested state with the `setStore(path, value)` and produce-style updates; ideal for objects/arrays where you want per-property tracking.
- **`createResource`** — async fetching tied to a source signal, exposing `.loading` and `.error`.
- **`createMemo` / `createEffect`** — derived values vs. side effects, plus `on()` for explicit dependencies and `untrack()` to opt out.
- Control flow via `<For>`, `<Index>`, `<Show>`, `<Switch>`, and concurrency via `<Suspense>` with `useTransition` / `startTransition`.
- SolidStart: file-based routing, `"use server"` functions, `cache()` / `createAsync`, and SSR entrypoints.

## Usage example

```tsx
import { createSignal, createResource } from "solid-js";

const fetchUser = (id: number) =>
  fetch(`/api/users/${id}`).then((r) => r.json());

function Profile() {
  const [id, setId] = createSignal(1);
  const [user] = createResource(id, fetchUser); // refetches when id() changes

  return (
    <Suspense fallback={<p>Loading…</p>}>
      <h1>{user()?.name}</h1>
      <button onClick={() => setId(id() + 1)}>Next</button>
    </Suspense>
  );
}
```

## Tips & gotchas

- **Never destructure props.** `const { name } = props` snapshots the value and kills reactivity. Read `props.name` at point of use, or use `splitProps`.
- Call signals as functions: `count()`, not `count`. A bare reference doesn't track.
- Prefer `<For>` for keyed lists and `<Index>` when the index is stable but items mutate — they have opposite re-render semantics.
- `createEffect` runs after render and re-tracks every read; use `on(source, fn)` when you want a single explicit dependency.

## FAQ

**Do I need a virtual DOM?** No. Solid compiles JSX to real DOM updates; only the exact nodes bound to a changed signal update.

**Signal vs. store?** Use a signal for a single value; use a store for nested objects/arrays so updates track individual properties without replacing the whole object.

**Is SolidStart required?** No — Solid runs standalone via Vite. SolidStart adds SSR, routing, and server functions when you need them.
