jpskill.com
🛠️ 開発・MCP コミュニティ

solid-js

SolidJSは、仮想DOMを使わない高速なUI構築ライブラリで、Reactからの移行も容易にし、SSRやサーバー機能を持つフルスタックアプリSolidStartにも対応、signals、effects、memosなどを活用して、より高性能なUIを開発するSkill。

📜 元の英語説明(参考)

SolidJS — fine-grained reactive UI library without a virtual DOM. Use when building high-performance UIs, choosing a React alternative with better reactivity primitives, or using SolidStart for full-stack apps with SSR and server functions. Covers signals, effects, memos, stores, and migration patterns from React.

🇯🇵 日本人クリエイター向け解説

一言でいうと

SolidJSは、仮想DOMを使わない高速なUI構築ライブラリで、Reactからの移行も容易にし、SSRやサーバー機能を持つフルスタックアプリSolidStartにも対応、signals、effects、memosなどを活用して、より高性能なUIを開発するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o solid-js.zip https://jpskill.com/download/15398.zip && unzip -o solid-js.zip && rm solid-js.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15398.zip -OutFile "$d\solid-js.zip"; Expand-Archive "$d\solid-js.zip" -DestinationPath $d -Force; ri "$d\solid-js.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して solid-js.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → solid-js フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

SolidJS

概要

SolidJS は、JSX を実際の DOM 操作にコンパイルする宣言的な UI ライブラリです。仮想 DOM や差分比較は行いません。リアクティビティはきめ細かく、変更されたデータに依存する正確な DOM ノードのみが更新されます。その結果、React のようなオーサリング体験で、ネイティブに近いパフォーマンスを実現します。

インストール

# 新しい SolidJS プロジェクト
npx degit solidjs/templates/ts my-app
cd my-app
npm install
npm run dev

# または Vite を使用する場合
npm create vite@latest my-app -- --template solid-ts

リアクティビティプリミティブ

createSignal — リアクティブな状態

import { createSignal } from "solid-js";

// シグナルは getter/setter のペアです
const [count, setCount] = createSignal(0);

// 読み取り: 関数として呼び出す
console.log(count()); // 0

// 書き込み: setter を呼び出す
setCount(1);
setCount((prev) => prev + 1); // アップデーター関数

// オブジェクトを持つシグナル
const [user, setUser] = createSignal({ name: "Alice", age: 30 });
setUser((prev) => ({ ...prev, age: 31 }));

createEffect — 副作用

import { createSignal, createEffect } from "solid-js";

const [name, setName] = createSignal("Alice");

// 即座に実行され、依存関係が変更されるたびに再実行されます
createEffect(() => {
  console.log("Name changed:", name());
  document.title = `Hello, ${name()}!`;
});

// クリーンアップ関数
createEffect(() => {
  const id = setInterval(() => console.log(name()), 1000);
  return () => clearInterval(id); // 次のエフェクトの前または破棄時に実行されます
});

createMemo — 派生状態

import { createSignal, createMemo } from "solid-js";

const [price, setPrice] = createSignal(100);
const [quantity, setQuantity] = createSignal(3);

// 計算された値 — 依存関係が変更された場合にのみ再計算されます
const total = createMemo(() => price() * quantity());

console.log(total()); // 300
setPrice(120);
console.log(total()); // 360 — 再計算されました

制御フロー

import { Show, For, Switch, Match, Index } from "solid-js";

// Show — 条件付きレンダリング
<Show when={isLoggedIn()} fallback={<LoginForm />}>
  <Dashboard />
</Show>

// For — リストのレンダリング (効率的なキー付き更新)
<For each={items()}>
  {(item, index) => <div>{index()} - {item.name}</div>}
</For>

// Index — 項目がその場で変更される場合 (並べ替えではない) のリストのレンダリング
<Index each={items()}>
  {(item, index) => <div>{index} - {item().name}</div>}
</Index>

// Switch/Match — 複数分岐の条件
<Switch fallback={<p>Unknown status</p>}>
  <Match when={status() === "loading"}><Spinner /></Match>
  <Match when={status() === "error"}><ErrorView /></Match>
  <Match when={status() === "success"}><DataView /></Match>
</Switch>

Stores — 複雑な状態

import { createStore, produce } from "solid-js/store";

const [state, setState] = createStore({
  users: [] as { id: number; name: string; active: boolean }[],
  loading: false,
});

// ネストされたプロパティの更新
setState("loading", true);
setState("users", 0, "active", false);

// produce を使用した Immer のようなミューテーション
setState(
  produce((s) => {
    s.users.push({ id: 4, name: "Diana", active: true });
    s.loading = false;
  })
);

Resources — 非同期データフェッチ

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

// createResource — 非同期データフェッチをラップします
async function fetchUser(id: number) {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new Error("User not found");
  return res.json();
}

function UserProfile() {
  const [userId, setUserId] = createSignal(1);

  // userId() が変更されると自動的に再フェッチされます
  const [user, { refetch, mutate }] = createResource(userId, fetchUser);

  return (
    <Suspense fallback={<p>Loading...</p>}>
      {/* user() はロード中は undefined で、準備ができたときに値になります */}
      <Show when={user()} fallback={<p>Error loading user</p>}>
        {(u) => (
          <div>
            <h1>{u().name}</h1>
            <button onClick={refetch}>Refresh</button>
          </div>
        )}
      </Show>
    </Suspense>
  );
}

SolidStart — フルスタック

SolidStart は、ファイルベースのルーティング、SSR、およびサーバー機能を追加します。

npm create solid@latest
# 選択: SolidStart, TypeScript

ファイル構造:

src/
  routes/
    index.tsx         → /
    about.tsx         → /about
    users/
      index.tsx       → /users
      [id].tsx        → /users/:id
  app.tsx
// src/routes/users/[id].tsx
import { createAsync, useParams } from "@solidjs/router";
import { Show, Suspense } from "solid-js";
import { getUser } from "~/lib/users"; // サーバー機能

export default function UserPage() {
  const params = useParams();
  const user = createAsync(() => getUser(Number(params.id)));

  return (
    <Suspense fallback={<p>Loading...</p>}>
      <Show when={user()}>
        {(u) => (
          <article>
            <h1>{u().name}</h1>
            <p>{u().email}</p>
          </article>
        )}
      </Show>
    </Suspense>
  );
}
// src/lib/users.ts — サーバー機能
"use server";

export async function getUser(id: number) {
  const res = await fetch(`https://api.example.com/users/${id}`);
  return res.json();
}

export async function createUser(data: { name: string; email: string }) {
  // サーバーでのみ実行されます — DB に安全にアクセスできます
  return db.insert(users).values(data).returning();
}

Context (依存性注入)

import { createContext, useContext, type ParentComponent } from "solid-js";
import { createStore } from "solid-js/store";

const AuthContext = createContext<{ user: () => User | null; login: (u: User) => void }>();

export const AuthProvider: ParentComponent = (props) => {
  const [state, setState] = createStore<{ user: User | null }>({ user: null });
  const value = { user: () => state.user, login: (u: User) => setState("user", u) };
  return <AuthContext.Provider value={value}>{props.children}</AuthContext.Provider>;
};

export const useAuth = () => useContext(AuthContext)!;

fr からの移行

(原文がここで切り詰められています)

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

SolidJS

Overview

SolidJS is a declarative UI library that compiles JSX to real DOM operations — no virtual DOM, no diffing. Reactivity is fine-grained: only the exact DOM nodes that depend on changed data update. The result is near-native performance with a React-like authoring experience.

Installation

# New SolidJS project
npx degit solidjs/templates/ts my-app
cd my-app
npm install
npm run dev

# Or with Vite
npm create vite@latest my-app -- --template solid-ts

Reactivity Primitives

createSignal — Reactive State

import { createSignal } from "solid-js";

// Signals are getter/setter pairs
const [count, setCount] = createSignal(0);

// Read: call as function
console.log(count()); // 0

// Write: call setter
setCount(1);
setCount((prev) => prev + 1); // Updater function

// Signals with objects
const [user, setUser] = createSignal({ name: "Alice", age: 30 });
setUser((prev) => ({ ...prev, age: 31 }));

createEffect — Side Effects

import { createSignal, createEffect } from "solid-js";

const [name, setName] = createSignal("Alice");

// Runs immediately, then reruns whenever dependencies change
createEffect(() => {
  console.log("Name changed:", name());
  document.title = `Hello, ${name()}!`;
});

// Cleanup function
createEffect(() => {
  const id = setInterval(() => console.log(name()), 1000);
  return () => clearInterval(id); // Runs before next effect or on dispose
});

createMemo — Derived State

import { createSignal, createMemo } from "solid-js";

const [price, setPrice] = createSignal(100);
const [quantity, setQuantity] = createSignal(3);

// Computed value — only recalculates when dependencies change
const total = createMemo(() => price() * quantity());

console.log(total()); // 300
setPrice(120);
console.log(total()); // 360 — recalculated

Control Flow

import { Show, For, Switch, Match, Index } from "solid-js";

// Show — conditional rendering
<Show when={isLoggedIn()} fallback={<LoginForm />}>
  <Dashboard />
</Show>

// For — list rendering (efficient keyed updates)
<For each={items()}>
  {(item, index) => <div>{index()} - {item.name}</div>}
</For>

// Index — list rendering when items change in place (not reorder)
<Index each={items()}>
  {(item, index) => <div>{index} - {item().name}</div>}
</Index>

// Switch/Match — multi-branch conditional
<Switch fallback={<p>Unknown status</p>}>
  <Match when={status() === "loading"}><Spinner /></Match>
  <Match when={status() === "error"}><ErrorView /></Match>
  <Match when={status() === "success"}><DataView /></Match>
</Switch>

Stores — Complex State

import { createStore, produce } from "solid-js/store";

const [state, setState] = createStore({
  users: [] as { id: number; name: string; active: boolean }[],
  loading: false,
});

// Update nested properties
setState("loading", true);
setState("users", 0, "active", false);

// Immer-like mutations with produce
setState(
  produce((s) => {
    s.users.push({ id: 4, name: "Diana", active: true });
    s.loading = false;
  })
);

Resources — Async Data Fetching

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

// createResource — wraps async data fetching
async function fetchUser(id: number) {
  const res = await fetch(`/api/users/${id}`);
  if (!res.ok) throw new Error("User not found");
  return res.json();
}

function UserProfile() {
  const [userId, setUserId] = createSignal(1);

  // Refetches automatically when userId() changes
  const [user, { refetch, mutate }] = createResource(userId, fetchUser);

  return (
    <Suspense fallback={<p>Loading...</p>}>
      {/* user() is undefined while loading, the value when ready */}
      <Show when={user()} fallback={<p>Error loading user</p>}>
        {(u) => (
          <div>
            <h1>{u().name}</h1>
            <button onClick={refetch}>Refresh</button>
          </div>
        )}
      </Show>
    </Suspense>
  );
}

SolidStart — Full-Stack

SolidStart adds file-based routing, SSR, and server functions:

npm create solid@latest
# Choose: SolidStart, TypeScript

File structure:

src/
  routes/
    index.tsx         → /
    about.tsx         → /about
    users/
      index.tsx       → /users
      [id].tsx        → /users/:id
  app.tsx
// src/routes/users/[id].tsx
import { createAsync, useParams } from "@solidjs/router";
import { Show, Suspense } from "solid-js";
import { getUser } from "~/lib/users"; // server function

export default function UserPage() {
  const params = useParams();
  const user = createAsync(() => getUser(Number(params.id)));

  return (
    <Suspense fallback={<p>Loading...</p>}>
      <Show when={user()}>
        {(u) => (
          <article>
            <h1>{u().name}</h1>
            <p>{u().email}</p>
          </article>
        )}
      </Show>
    </Suspense>
  );
}
// src/lib/users.ts — server functions
"use server";

export async function getUser(id: number) {
  const res = await fetch(`https://api.example.com/users/${id}`);
  return res.json();
}

export async function createUser(data: { name: string; email: string }) {
  // Runs on the server only — safe to access DB
  return db.insert(users).values(data).returning();
}

Context (Dependency Injection)

import { createContext, useContext, type ParentComponent } from "solid-js";
import { createStore } from "solid-js/store";

const AuthContext = createContext<{ user: () => User | null; login: (u: User) => void }>();

export const AuthProvider: ParentComponent = (props) => {
  const [state, setState] = createStore<{ user: User | null }>({ user: null });
  const value = { user: () => state.user, login: (u: User) => setState("user", u) };
  return <AuthContext.Provider value={value}>{props.children}</AuthContext.Provider>;
};

export const useAuth = () => useContext(AuthContext)!;

Migrating from React

React SolidJS
useState(0) createSignal(0)
useEffect(() => {}, [dep]) createEffect(() => { dep(); })
useMemo(() => calc, [dep]) createMemo(() => calc())
useReducer createStore
useContext useContext (same API)
React.memo Not needed — no re-renders
key prop in lists Use <For> instead of map()
useRef createSignal or let el!: HTMLElement

Key differences:

  • Components run once — no "re-render" concept. Put reactive logic inside JSX or effects.
  • Access signals by calling themcount() not count.
  • Use <For> for lists — not .map() — for efficient keyed rendering.
  • Destructuring signals breaks reactivity — pass signals or use stores.

Guidelines

  • Never destructure signals: const { x } = state breaks reactivity. Use state.x or createMemo.
  • Use <For> instead of Array.map in JSX for efficient list rendering.
  • Components run once — initialize logic at the top level, not in callbacks.
  • Use createStore for objects/arrays that need fine-grained updates.
  • Use createResource for async data — it integrates with <Suspense> automatically.
  • createMemo is cached — prefer it over calling createEffect to compute derived values.
  • SolidStart "use server" functions run exclusively on the server — safe for DB access.