From solidjs
Implements SolidJS reactive patterns using signals, effects, and memos. Use when writing or reviewing SolidJS components, state management, or reactive code. Covers the core mental model: components run once, signals track in reactive scopes, and props must not be destructured.
How this skill is triggered — by the user, by Claude, or both
Slash command
/solidjs:solidjs-reactivityThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
SolidJS is NOT React. The fundamental differences:
SolidJS is NOT React. The fundamental differences:
// The component function runs ONCE. Only the {count()} expression re-evaluates.
function Counter() {
const [count, setCount] = createSignal(0);
console.log("This logs once, not on every update");
return <button onClick={() => setCount(c => c + 1)}>{count()}</button>;
}
Creates a reactive value with a getter (accessor) and setter.
import { createSignal } from "solid-js";
const [count, setCount] = createSignal(0);
// Read: call the getter — signals are functions
count(); // 0
// Write: call the setter
setCount(5);
setCount(prev => prev + 1);
Options:
// Custom equality — skip update if values are "equal"
const [data, setData] = createSignal(initialData, {
equals: (prev, next) => prev.id === next.id,
});
// Always notify — useful for triggering effects on every set
const [trigger, setTrigger] = createSignal(undefined, { equals: false });
Key rule: Signal getters must be called (with ()) to read the value. count is a function, count() is the value.
Signals are only tracked when read inside a tracking scope. These are:
<div>{count()}</div>createEffect(() => console.log(count()))createMemo(() => count() * 2)Reading a signal outside these scopes does NOT create a subscription:
function MyComponent() {
const [count, setCount] = createSignal(0);
// NOT tracked — runs once during component setup
console.log(count());
// Tracked — re-runs when count changes
createEffect(() => {
console.log(count()); // tracked
});
// Tracked — JSX expressions are tracking scopes
return <div>{count()}</div>;
}
Runs side effects when dependencies change. Tracks signals automatically.
import { createSignal, createEffect, onCleanup } from "solid-js";
function Timer() {
const [count, setCount] = createSignal(0);
createEffect(() => {
const id = setInterval(() => setCount(c => c + 1), 1000);
onCleanup(() => clearInterval(id)); // cleanup on re-run or disposal
});
return <span>{count()}</span>;
}
Execution timing:
Cleanup: Use onCleanup inside an effect to clean up before re-execution or disposal.
Creates a cached derived value. Only recalculates when dependencies change.
import { createSignal, createMemo } from "solid-js";
function FilteredList() {
const [query, setQuery] = createSignal("");
const [items] = createSignal(["apple", "banana", "cherry"]);
// Recalculates only when query() or items() change
const filtered = createMemo(() =>
items().filter(item => item.includes(query()))
);
return <ul><For each={filtered()}>{item => <li>{item}</li>}</For></ul>;
}
Memo vs derived signal (plain function):
// Derived signal — recalculates every time it's read
const doubled = () => count() * 2;
// Memo — caches result, recalculates only when count changes
const doubled = createMemo(() => count() * 2);
Use createMemo when:
Use a plain derived signal when:
Groups multiple signal updates so downstream computations run once.
import { batch } from "solid-js";
batch(() => {
setFirstName("John");
setLastName("Doe");
setAge(30);
}); // Effects/memos that depend on these signals update once here
Automatic batching: Updates inside createEffect, onMount, and store setters are already batched. You rarely need explicit batch().
Important: If batch callback is async, only updates before the first await are batched.
Reads a signal without creating a tracking dependency.
import { untrack } from "solid-js";
createEffect(() => {
// count() is tracked, name() is NOT tracked
console.log(count(), untrack(() => name()));
});
Use untrack when you need a signal's current value without subscribing to changes.
The most common mistakes when writing SolidJS code are documented in detail in the PITFALLS.md companion file. The top issues:
() on signal gettersstopPropagation with delegated eventsnpx claudepluginhub ilyagulya/claude-marketplace --plugin solidjsSOLID principles for React 19. Files < 100 lines, hooks separated, interfaces in src/interfaces/, JSDoc mandatory. Use for React architecture and code quality.
React component discipline: pure components, minimal state, effects as escape hatches. Invoke whenever task involves any interaction with React code — writing, reviewing, refactoring, debugging, or understanding JSX, hooks, component architecture, state management, or performance optimization.
Provides best practices for Svelte runes: $state for reactive variables, $derived for computations, minimal $effect use, reactive $props handling, and $inspect.trace debugging. For Svelte component writing, editing, analysis.