mcpField
G
generic-react-feature-developer

generic-react-feature-developer

github.com/travisjneuman開発106134 回インストール1 日前に更新
リポジトリ

generic-react-feature-developer について

Reactの機能開発に向け、アーキテクチャ、状態管理、データ取得、永続化、コンポーネント設計の指針を示すスキルです。Reactアプリを構築・拡張する開発者を対象としています。

主な機能

  1. 01Reactプロジェクト構成の指針
  2. 02ZustandとContextの状態管理パターン
  3. 03React Queryによるサーバー状態管理
  4. 04IndexedDBサービスの設計パターン
  5. 05遅延読み込みとコード分割
  6. 06カスタムフックとコンポーネント構成

活用シーン

  1. 01機能ごとの状態管理方式の計画
  2. 02大容量データやバイナリデータの永続化
  3. 03コンポーネントの遅延読み込みによる初期負荷の軽減

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/travisjneuman/.claude --skill generic-react-feature-developer

インストール後、Claude Code で/generic-react-feature-developerを入力して読み込まれたか確認します。

詳細

React 機能開発者

React のアーキテクチャパターンに沿って、機能開発を進めます。

拡張元: 汎用機能開発者 - 開発ワークフロー、スコープの評価、構築と統合の判断については、基本スキルをお読みください。

React アーキテクチャ

プロジェクト構成
src/
├── components/
│   ├── ui/          # Reusable primitives (Button, Input)
│   ├── features/    # Feature-specific components
│   └── layout/      # Layout components (Header, Sidebar)
├── hooks/           # Custom hooks (useAuth, useStore)
├── stores/          # Zustand stores
├── services/        # API clients, IndexedDB wrappers
├── types/           # TypeScript interfaces
└── lib/             # Utilities

状態管理パターン

Zustand ストア(推奨)
// stores/useFeatureStore.ts
interface FeatureState {
  items: Item[];
  isLoading: boolean;
  // Actions
  addItem: (item: Item) => void;
  removeItem: (id: string) => void;
}

const useFeatureStore = create<FeatureState>()(
  persist(
    (set) => ({
      items: [],
      isLoading: false,
      addItem: (item) => set((s) => ({ items: [...s.items, item] })),
      removeItem: (id) =>
        set((s) => ({
          items: s.items.filter((i) => i.id !== id),
        })),
    }),
    {
      name: "feature-storage",
      version: 1,
      migrate: (state, version) => {
        // Handle migrations between versions
        return state as FeatureState;
      },
    },
  ),
);
Zustand セレクター(パフォーマンス)
// Avoid re-renders with selectors
const items = useFeatureStore((state) => state.items);
const addItem = useFeatureStore((state) => state.addItem);

// Shallow compare for objects
import { shallow } from "zustand/shallow";
const { items, isLoading } = useFeatureStore(
  (state) => ({ items: state.items, isLoading: state.isLoading }),
  shallow,
);
Context と Zustand の使い分け
Context を使う場合Zustand を使う場合
テーマ、ロケール(変更頻度が低い)頻繁に更新されるデータ
認証状態アクションを伴う複雑な状態
プロバイダーがすでに存在する場合永続化が必要な場合
1~2 階層のプロップのバケツリレー複数の領域に関わる懸念事項

サーバー状態(React Query)

// Server state - React Query
const { data, isLoading, error } = useQuery({
  queryKey: ["items", userId],
  queryFn: () => fetchItems(userId),
  staleTime: 5 * 60 * 1000, // 5 minutes
});

// Mutations
const mutation = useMutation({
  mutationFn: createItem,
  onSuccess: () => {
    queryClient.invalidateQueries({ queryKey: ["items"] });
  },
});

IndexedDB の統合

使用するタイミング
シナリオ解決策
合計 5 MB 未満Zustand persist 経由の localStorage
合計 5 MB 超IndexedDB
バイナリデータ(画像、ファイル)IndexedDB
シンプルなキーと値localStorage
複雑なクエリIndexedDB
サービスラッパーパターン
// services/indexedDBService.ts
class IndexedDBService {
  private db: IDBDatabase | null = null;

  async init() {
    return new Promise<void>((resolve, reject) => {
      const request = indexedDB.open("AppDB", 1);
      request.onerror = () => reject(request.error);
      request.onsuccess = () => {
        this.db = request.result;
        resolve();
      };
      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result;
        db.createObjectStore("items", { keyPath: "id" });
      };
    });
  }

  async setItem<T>(store: string, value: T): Promise<void> {
    // Implementation
  }

  async getItem<T>(store: string, key: string): Promise<T | null> {
    // Implementation
  }
}

export const indexedDBService = new IndexedDBService();

遅延読み込み

コンポーネントの遅延読み込み
// Heavy components (>20KB)
const HeavyChart = lazy(() => import('./HeavyChart'));
const RichTextEditor = lazy(() => import('./RichTextEditor'));

// Pages
const SettingsPage = lazy(() => import('./pages/Settings'));

// Usage with Suspense
<Suspense fallback={<Skeleton />}>
  <HeavyChart data={data} />
</Suspense>
ルートレベルのコード分割
// React Router example
const routes = [
  {
    path: '/dashboard',
    element: <DashboardLayout />,
    children: [
      {
        path: 'settings',
        lazy: () => import('./pages/Settings'),
      },
    ],
  },
];

カスタムフックのパターン

機能フック
// hooks/useItems.ts
function useItems() {
  const items = useFeatureStore((s) => s.items);
  const addItem = useFeatureStore((s) => s.addItem);

  const sortedItems = useMemo(
    () => [...items].sort((a, b) => b.createdAt - a.createdAt),
    [items],
  );

  return { items: sortedItems, addItem };
}
複合フック(複数のソースの組み合わせ)
// hooks/useDashboard.ts
function useDashboard() {
  // Local state
  const [filter, setFilter] = useState("all");

  // Server state
  const { data: items } = useQuery({ queryKey: ["items"] });

  // Client state
  const preferences = usePreferencesStore((s) => s.dashboard);

  // Derived
  const filteredItems = useMemo(
    () => items?.filter((i) => filter === "all" || i.status === filter),
    [items, filter],
  );

  return { filter, setFilter, items: filteredItems, preferences };
}

コンポーネントのコンポジション

複合コンポーネント
// Usage: <Tabs><Tabs.List /><Tabs.Panel /></Tabs>
const TabsContext = createContext<TabsContextValue | null>(null);

function Tabs({ children, defaultValue }: TabsProps) {
  const [active, setActive] = useState(defaultValue);
  return (
    <TabsContext.Provider value={{ active, setActive }}>
      {children}
    </TabsContext.Provider>
  );
}

Tabs.List = function TabsList({ children }: { children: ReactNode }) {
  return <div role="tablist">{children}</div>;
};

Tabs.Panel = function TabsPanel({ value, children }: TabsPanelProps) {
  const { active } = useContext(TabsContext)!;
  if (value !== active) return null;
  return <div role="tabpanel">{children}</div>;
};

React 機能チェックリスト

開始前:

  • プロジェクトのパターンを把握するために CLAUDE.md を読む
  • 再利用できる既存のコンポーネントを確認する
  • 状態管理の方針を計画する
  • バンドルサイズへの影響を見積もる

開発中:

  • プロジェクトのデザインシステムに従う
  • TypeScript の strict モードを使用する
  • キーボード操作を実装する
  • ARIA ラベルを追加する
  • ダークモードに対応する

完了前:

  • ユーザーから依頼された場合にのみユニットテストを作成する
  • 重いコンポーネントを遅延読み込みする
  • 新しいインポートと依存関係によるバンドルへの影響を確認する
  • code-reviewer スキルを使ってレビューする

関連項目

コメント