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

pitfalls-react

React component patterns, forms, accessibility, and responsive design. Use when building React components, handling forms, or ensuring accessibility. Triggers on: React component, useEffect, form validation, a11y, responsive, Error Boundary.

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

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

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

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

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して pitfalls-react.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → pitfalls-react フォルダができる
  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 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

React の落とし穴

React 開発におけるよくある落とし穴と正しいパターンについて説明します。

どのような時に使うか

  • React コンポーネントの構築
  • フォームのバリデーションの実装
  • エラー境界の追加
  • アクセシビリティ (a11y) の確保
  • レスポンシブなレイアウトの作成
  • React コードのレビュー

ワークフロー

ステップ 1: コンポーネントのパターンをチェックする

ローディング/エラー状態とデータのチェックを確認します。

ステップ 2: フォームのバリデーションを確認する

Zod スキーマと適切なエラー表示を確実にします。

ステップ 3: アクセシビリティをチェックする

ARIA ラベルとキーボードナビゲーションを確認します。


コンポーネントのパターン

// ✅ ヘルパー関数は使用前に定義するか、エクスポートする
function formatPrice(price: number) { ... }

export default function Component() {
  // ✅ データが存在することを確認してからアクセスする
  if (!data) return <Loading />;

  // ✅ 副作用のためだけに useEffect を使用する
  useEffect(() => {
    fetchData();
  }, []);

  // ✅ インタラクティブな要素に data-testid を付与する
  return <button data-testid="submit-btn">Submit</button>;
}

// ❌ 間違い: レンダリング内で関数を定義する
return <button onClick={() => {
  function doSomething() { } // ここで定義しない
  doSomething();
}}>

// ✅ router を使用したナビゲーション、window は使用しない
import { Link, useLocation } from 'wouter';
<Link to="/dashboard">Go</Link>
// ❌ window.location.href = '/dashboard'

エラー境界

// ✅ 主要なコンポーネントをエラー境界で囲む
class ErrorBoundary extends React.Component {
  state = { hasError: false, error: null };

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, info) {
    logError({ error, componentStack: info.componentStack });
  }

  render() {
    if (this.state.hasError) {
      return <ErrorFallback onRetry={() => this.setState({ hasError: false })} />;
    }
    return this.props.children;
  }
}

// ✅ グレースフルデグラデーション
function Dashboard() {
  const { data, error, isLoading } = useQuery(...);

  if (isLoading) return <Skeleton />;
  if (error) return <ErrorCard message="Unable to load" onRetry={refetch} />;
  if (!data) return <EmptyState />;

  return <DashboardContent data={data} />;
}

フォームのバリデーション

// ✅ すべてのフォームに Zod スキーマを使用する
const createStrategySchema = z.object({
  name: z.string().min(1, 'Name required').max(100),
  type: z.enum(['cross-exchange', 'triangular']),
  minProfit: z.number().positive('Must be positive'),
});

// ✅ Zod を使用した React Hook Form
const form = useForm<z.infer<typeof createStrategySchema>>({
  resolver: zodResolver(createStrategySchema),
});

// ✅ エラーをインラインで表示する
{errors.name && <span className="text-red-500">{errors.name.message}</span>}

// ✅ バリデーション/送信中は送信を無効にする
<button disabled={isSubmitting || !isValid}>Submit</button>

レスポンシブなレイアウト

/* ✅ モバイルファーストのブレークポイント */
.container { padding: 1rem; }

@media (min-width: 768px) {
  .container { padding: 2rem; }
}

/* ✅ タッチフレンドリーなボタンサイズ (最小 44px) */
.btn { min-height: 44px; min-width: 44px; }

/* ✅ モバイルでのデータテーブルの水平スクロール */
.table-container { overflow-x: auto; }

アクセシビリティ (a11y)

// ✅ セマンティック HTML
<nav>...</nav>
<main>...</main>
<button>Click me</button>  // <div onClick> ではない

// ✅ ARIA ラベル
<button aria-label="Close dialog">×</button>

// ✅ キーボードナビゲーション
<button onKeyDown={(e) => e.key === 'Enter' && handleClick()}>

// ✅ フォーカスインジケーター
button:focus { outline: 2px solid blue; outline-offset: 2px; }

簡単なチェックリスト

  • [ ] ローディング/エラー状態が処理されている
  • [ ] インタラクティブな要素に data-testid が付与されている
  • [ ] window.location ではなく、router の Link を使用している
  • [ ] ヘルパー関数は使用前に定義されている
  • [ ] 主要なコンポーネントにエラー境界がある
  • [ ] タッチターゲットが 44px 以上である
  • [ ] アイコンボタンに ARIA ラベルが付与されている
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

React Pitfalls

Common pitfalls and correct patterns for React development.

When to Use

  • Building React components
  • Implementing form validation
  • Adding error boundaries
  • Ensuring accessibility (a11y)
  • Creating responsive layouts
  • Reviewing React code

Workflow

Step 1: Check Component Patterns

Verify loading/error states and data checks.

Step 2: Verify Form Validation

Ensure Zod schemas and proper error display.

Step 3: Check Accessibility

Verify ARIA labels and keyboard navigation.


Component Patterns

// ✅ Define helpers before use or as exports
function formatPrice(price: number) { ... }

export default function Component() {
  // ✅ Check data exists before accessing
  if (!data) return <Loading />;

  // ✅ useEffect for side effects only
  useEffect(() => {
    fetchData();
  }, []);

  // ✅ data-testid on interactive elements
  return <button data-testid="submit-btn">Submit</button>;
}

// ❌ WRONG: Defining function in render
return <button onClick={() => {
  function doSomething() { } // Don't define here
  doSomething();
}}>

// ✅ Navigation with router, not window
import { Link, useLocation } from 'wouter';
<Link to="/dashboard">Go</Link>
// ❌ window.location.href = '/dashboard'

Error Boundary

// ✅ Wrap major components in error boundaries
class ErrorBoundary extends React.Component {
  state = { hasError: false, error: null };

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, info) {
    logError({ error, componentStack: info.componentStack });
  }

  render() {
    if (this.state.hasError) {
      return <ErrorFallback onRetry={() => this.setState({ hasError: false })} />;
    }
    return this.props.children;
  }
}

// ✅ Graceful degradation
function Dashboard() {
  const { data, error, isLoading } = useQuery(...);

  if (isLoading) return <Skeleton />;
  if (error) return <ErrorCard message="Unable to load" onRetry={refetch} />;
  if (!data) return <EmptyState />;

  return <DashboardContent data={data} />;
}

Form Validation

// ✅ Zod schemas for all forms
const createStrategySchema = z.object({
  name: z.string().min(1, 'Name required').max(100),
  type: z.enum(['cross-exchange', 'triangular']),
  minProfit: z.number().positive('Must be positive'),
});

// ✅ React Hook Form with Zod
const form = useForm<z.infer<typeof createStrategySchema>>({
  resolver: zodResolver(createStrategySchema),
});

// ✅ Show errors inline
{errors.name && <span className="text-red-500">{errors.name.message}</span>}

// ✅ Disable submit while validating/submitting
<button disabled={isSubmitting || !isValid}>Submit</button>

Responsive Layout

/* ✅ Mobile-first breakpoints */
.container { padding: 1rem; }

@media (min-width: 768px) {
  .container { padding: 2rem; }
}

/* ✅ Touch-friendly button sizes (min 44px) */
.btn { min-height: 44px; min-width: 44px; }

/* ✅ Horizontal scroll for data tables on mobile */
.table-container { overflow-x: auto; }

Accessibility (a11y)

// ✅ Semantic HTML
<nav>...</nav>
<main>...</main>
<button>Click me</button>  // Not <div onClick>

// ✅ ARIA labels
<button aria-label="Close dialog">×</button>

// ✅ Keyboard navigation
<button onKeyDown={(e) => e.key === 'Enter' && handleClick()}>

// ✅ Focus indicators
button:focus { outline: 2px solid blue; outline-offset: 2px; }

Quick Checklist

  • [ ] Loading/error states handled
  • [ ] data-testid on interactive elements
  • [ ] Using router Link, not window.location
  • [ ] Helper functions defined before use
  • [ ] Error boundaries on major components
  • [ ] Touch targets ≥ 44px
  • [ ] ARIA labels on icon buttons