docs-sandpack について
docs-sandpackは、React Sandpackの例を作成するためのドキュメント執筆スキルです。ファイル構成、コードスタイル、行の強調表示、依存関係の設定方法をまとめています。
主な機能
- 01単一・複数ファイルの例の構成
- 02ファイル名と表示設定の規則
- 03コード行の強調と参照マーカー
- 04React例のスタイル要件
- 05依存関係とpackage.jsonの指針
活用シーン
- 01ドキュメント用React例の作成
- 02複数ファイルにまたがる例の構成
- 03コード行と想定エラーの指定
- 04Sandpack例のスタイル確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ reactjs/ react.dev --skill docs-sandpackインストール後、Claude Code で/docs-sandpackを入力して読み込まれたか確認します。
詳細
Sandpack のパターン
クイックスタートテンプレート
ほとんどの例は単一ファイルです。これをコピーして変更してください。
<Sandpack>
` ` `js
import { useState } from 'react';
export default function Example() {
const [value, setValue] = useState(0);
return (
<button onClick={() => setValue(value + 1)}>
Clicked {value} times
</button>
);
}
` ` `
</Sandpack>
ファイル名
| パターン | 用途 |
|---|---|
```js | メインファイル(接頭辞なし) |
```js src/FileName.js | 補助ファイル |
```js src/File.js active | アクティブなファイル(リファレンスページ) |
```js src/data.js hidden | 非表示ファイル |
```css | CSS スタイル |
```json package.json | 外部依存関係 |
重要: メインファイルには必ず export default を含めてください。
行のハイライト
```js {2-4}
function Example() {
// Lines 2-4
// will be
// highlighted
return null;
}
コード参照(番号付きコールアウト)
```js [[1, 4, "age"], [2, 4, "setAge"]]
// Creates numbered markers pointing to "age" and "setAge" on line 4
予期されるエラー(意図的に壊した例)
```js {expectedErrors: {'react-compiler': [7]}}
// Line 7 shows as expected error
複数ファイルの例
<Sandpack>
```js src/App.js
import Gallery from './Gallery.js';
export default function App() {
return <Gallery />;
}
export default function Gallery() {
return <h1>Gallery</h1>;
}
h1 { color: purple; }
```
External Dependencies
<Sandpack>
```js
import { useImmer } from 'use-immer';
// ...
{
"dependencies": {
"immer": "1.7.3",
"use-immer": "0.5.1",
"react": "latest",
"react-dom": "latest",
"react-scripts": "latest"
}
}
```
Code Style in Sandpack (Required)
Sandpack examples are held to strict code style standards:
- Function declarations for components (not arrows)
efor event parameters- Single quotes in JSX
constunless reassignment needed- Spaces in destructuring:
({ props })not({props}) - Two-line createRoot: separate declaration and render call
- Multiline if statements: always use braces
Don't Create Hydration Mismatches
Sandpack examples must produce the same output on server and client:
// 🚫 This will cause hydration warnings
export default function App() {
const isClient = typeof window !== 'undefined';
return <div>{isClient ? 'Client' : 'Server'}</div>;
}
レンダリングされない状態には Ref を使用する
// 🚫 Don't trigger re-renders for non-visual state
const [mounted, setMounted] = useState(false);
useEffect(() => { setMounted(true); }, []);
// ✅ Use ref instead
const mounted = useRef(false);
useEffect(() => { mounted.current = true; }, []);
forwardRef と memo のパターン
forwardRef - 名前付き関数を使用する
// ✅ Named function for DevTools display name
const MyInput = forwardRef(function MyInput(props, ref) {
return <input {...props} ref={ref} />;
});
// 🚫 Anonymous loses name
const MyInput = forwardRef((props, ref) => { ... });
memo - 名前付き関数を使用する
// ✅ Preserves component name
const Greeting = memo(function Greeting({ name }) {
return <h1>Hello, {name}</h1>;
});
行の長さ
- 説明文:約80文字
- コード:約60~70文字
- 横スクロールを避けるため、長い行は折り返してください
アンチパターン
| パターン | 問題 | 修正 |
|---|---|---|
const Comp = () => {} | 標準的ではない | function Comp() {} |
onClick={(event) => ...} | グローバル名と競合する | onClick={(e) => ...} |
レンダリングされない値に useState を使用する | 再レンダリングされる | useRef を使用する |
レンダリング中に window を読み取る | ハイドレーションの不一致 | useEffect 内で確認する |
| 波括弧なしの1行 if | デバッグしにくい | 波括弧を使って複数行にする |
createRoot().render() の連結 | わかりにくい | 2つの文に分ける |
スペースなしの //... | 一貫性がない | スペースを入れて // ... とする |
| タブ | 一貫性がない | 2つのスペース |
ReactDOM.render | 非推奨 | createRoot を使用する |
| 架空のパッケージ名 | 混乱を招く | './your-storage-layer' を使用する |
PropsWithChildren | 古い形式 | children?: ReactNode |
リスト内の key の欠落 | 警告が表示される | 必ず key を含める |
追加のコード品質ルール
リストには必ず Key を含める
// ✅ Correct
{items.map(item => <li key={item.id}>{item.name}</li>)}
// 🚫 Wrong - missing key
{items.map(item => <li>{item.name}</li>)}
現実的なインポートパスを使用する
// ✅ Correct - descriptive path
import { fetchData } from './your-data-layer';
// 🚫 Wrong - looks like a real npm package
import { fetchData } from 'cool-data-lib';
Console.log のラベル
// ✅ Correct - labeled for clarity
console.log('User:', user);
console.log('Component Stack:', errorInfo.componentStack);
// 🚫 Wrong - unlabeled
console.log(user);
遅延時間は適切に保つ
// ✅ Correct - 1-1.5 seconds
setTimeout(() => setLoading(false), 1000);
// 🚫 Wrong - too long, feels sluggish
setTimeout(() => setLoading(false), 3000);
行のハイライトの更新
行のハイライト({2-4})を使用する例のコードを変更するときは、新しいコードに合うよう、必ずハイライトの行番号を更新してください。行番号が正しくないと、レンダリング時にクラッシュします。
ファイル名の規則
- コンポーネントファイルのファイル名は大文字で始めます。
gallery.jsではなくGallery.jsを使用してください。 - ファイルが
src/内にあることを最初に説明した後は、src/Gallery.jsではなくGallery.jsのように、ファイル名だけで参照してください。
コード内の命名規則
コンポーネント: PascalCase
Profile、Avatar、TodoList、PackingList
状態変数: 分割代入のパターン
const [count, setCount] = useState(0)- ブール値:
[isOnline, setIsOnline]、[isPacked, setIsPacked] - 状態を表す文字列:
'typing'、'submitting'、'success'、'error'
イベントハンドラー:
handleClick、handleSubmit、handleAddTask
コールバック用 Props:
onClick、onChange、onAddTask、onSelect
カスタムフック:
useOnlineStatus、useChatRoom、useFormInput
Reducer のアクション:
- 過去形:
'added'、'changed'、'deleted' - 複合語はスネークケース:
'changed_selection'、'sent_message'
更新関数: 1文字を使用する
setCount(n => n + 1)
教育目的のコードマーカー
誤ったコードと正しいコード:
// 🔴 Avoid: redundant state and unnecessary Effect
// ✅ Good: calculated during rendering
ライフサイクルの説明用 Console.log:
console.log('✅ Connecting...');
console.log('❌ Disconnected.');
サーバー/クライアントのラベル付け
// Server Component
async function Notes() {
const notes = await db.notes.getAll();
}
// Client Component
"use client"
export default function Expandable({children}) {
const [expanded, setExpanded] = useState(false);
}
バンドルサイズの注記
import marked from 'marked'; // 35.9K (11.2K gzipped)
import sanitizeHtml from 'sanitize-html'; // 206K (63.3K gzipped)
Sandpack の例に関するガイドライン
Package.json のルール
package.json を含める場合:
- 外部 npm パッケージ(immer、remarkable、leaflet、toastify-js など)を使用する
- 実験的またはカナリア版の React 機能を紹介する
- 特定の React バージョンが必要(
react: beta、react: 19.0.0-rc-*)
package.json を省略する場合:
- 例が React の組み込み機能のみを使用する
- 外部依存関係が不要である
- 基本的なフック、状態、またはコンポーネントについて説明する
package.json は必ず hidden としてマークする:
```json package.json hidden
{
"dependencies": {
"react": "latest",
"react-dom": "latest",
"react-scripts": "latest",
"immer": "1.7.3"
}
}
**Version conventions:**
- Use `"latest"` for stable features
- Use exact versions only when compatibility requires it
- Include minimal dependencies (just what the example needs)
### Hidden File Patterns
**Always hide these file types:**
| File Type | Reason |
|-----------|--------|
| `package.json` | Configuration not the teaching point |
| `sandbox.config.json` | Sandbox setup is boilerplate |
| `public/index.html` | HTML structure not the focus |
| `src/data.js` | When it contains sample/mock data |
| `src/api.js` | When showing API usage, not implementation |
| `src/styles.css` | When styling is not the lesson |
| `src/router.js` | Supporting infrastructure |
| `src/actions.js` | Server action implementation details |
**Rationale:**
- Reduces cognitive load
- Keeps focus on the primary concept
- Creates cleaner, more focused examples
**Example:**
```mdx
```js src/data.js hidden
export const items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
];
### Active File Patterns
**Mark as active when:**
- File contains the primary teaching concept
- Learner should focus on this code first
- Component demonstrates the hook/pattern being taught
**Effect of the `active` marker:**
- Sets initial editor tab focus when Sandpack loads
- Signals "this is what you should study"
- Works with hidden files to create focused examples
**Most common active file:** `src/index.js` or `src/App.js`
**Example:**
```mdx
```js src/App.js active
// This file will be focused when example loads
export default function App() {
// ...
}
### File Structure Guidelines
| Scenario | Structure | Reason |
|----------|-----------|--------|
| Basic hook usage | Single file | Simple, focused |
| Teaching imports | 2-3 files | Shows modularity |
| Context patterns | 4-5 files | Realistic structure |
| Complex state | 3+ files | Separation of concerns |
**Single File Examples (70% of cases):**
- Use for simple concepts
- 50-200 lines typical
- Best for: Counter, text inputs, basic hooks
**Multi-File Examples (30% of cases):**
- Use when teaching modularity/imports
- Use for context patterns (4-5 files)
- Use when component is reused
**File Naming:**
- Main component: `App.js` (capitalized)
- Component files: `Gallery.js`, `Button.js` (capitalized)
- Data files: `data.js` (lowercase)
- Utility files: `utils.js` (lowercase)
- Context files: `TasksContext.js` (named after what they provide)
### Code Size Limits
- Single file: **<200 lines**
- Multi-file total: **150-300 lines**
- Main component: **100-150 lines**
- Supporting files: **20-40 lines each**
### CSS Guidelines
**Always:**
- Include minimal CSS for demo interactivity
- Use semantic class names (`.panel`, `.button-primary`, `.panel-dark`)
- Support light/dark themes when showing UI concepts
- Keep CSS visible (never hidden)
**Size Guidelines:**
- Minimal (5-10 lines): Basic button styling, spacing
- Medium (15-30 lines): Panel styling, form layouts
- Complex (40+ lines): Only for layout-focused examples
コメント
Markdown 対応