mcpField
R
react

react

github.com/thelobbi開発2147 回インストール5 日前に更新
リポジトリ

react について

モダンなフロントエンド開発向けの React スキルです。コンポーネント、Hooks、状態管理、Context API に加え、データ取得、フォーム、パフォーマンス最適化の例を扱います。

主な機能

  1. 01コンポーネントと合成パターン
  2. 02Hooks と状態管理
  3. 03Context API
  4. 04React Query によるデータ取得
  5. 05フォームの検証と処理
  6. 06コンポーネントの最適化

活用シーン

  1. 01React コンポーネントとカスタム Hooks の実装
  2. 02コンポーネント間の状態管理
  3. 03データ取得とフォーム送信
  4. 04リスト描画の最適化

インストール

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

$npx skills add https://github.com/thelobbi/claude --skill react

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

詳細

React スキル

モダンなフロントエンドアプリケーション向けに、包括的な React 開発機能を提供します。

このスキルを使用するタイミング

以下の作業を行う際に、このスキルを有効にしてください。

  • React コンポーネントの開発
  • フックの実装
  • 状態管理
  • Context API の使用
  • コンポーネントのパターンと合成

プロジェクト構造

``` src/ ├── components/ │ ├── ui/ │ │ ├── Button.tsx │ │ └── Card.tsx │ └── features/ │ ├── AgentList.tsx │ └── TaskPanel.tsx ├── hooks/ │ ├── useAgent.ts │ └── useTask.ts ├── context/ │ └── AgentContext.tsx ├── services/ │ └── api.ts ├── types/ │ └── index.ts └── App.tsx ```

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

関数コンポーネント

```tsx import { FC } from 'react';

interface AgentCardProps { name: string; type: 'claude' | 'gpt' | 'gemini'; status: 'active' | 'idle' | 'error'; onSelect?: () => void; }

export const AgentCard: FC = ({ name, type, status, onSelect }) => { return (

{name}
<span className={status status-${status}}>{status} {type}
); }; ```

カスタムフック

```tsx import { useState, useEffect, useCallback } from 'react';

interface Agent { id: string; name: string; status: string; }

export function useAgent(agentId: string) { const [agent, setAgent] = useState<Agent | null>(null); const [loading, setLoading] = useState(true); const [error, setError] = useState<Error | null>(null);

useEffect(() => { const fetchAgent = async () => { try { setLoading(true); const response = await fetch(/api/agents/${agentId}); const data = await response.json(); setAgent(data); } catch (err) { setError(err as Error); } finally { setLoading(false); } };

fetchAgent();

}, [agentId]);

const refresh = useCallback(() => { // 再取得を実行 }, [agentId]);

return { agent, loading, error, refresh }; } ```

Context プロバイダー

```tsx import { createContext, useContext, useReducer, ReactNode } from 'react';

interface AgentState { agents: Agent[]; selectedAgent: Agent | null; }

type AgentAction = | { type: 'SET_AGENTS'; payload: Agent[] } | { type: 'SELECT_AGENT'; payload: Agent } | { type: 'CLEAR_SELECTION' };

const AgentContext = createContext<{ state: AgentState; dispatch: React.Dispatch; } | null>(null);

function agentReducer(state: AgentState, action: AgentAction): AgentState { switch (action.type) { case 'SET_AGENTS': return { ...state, agents: action.payload }; case 'SELECT_AGENT': return { ...state, selectedAgent: action.payload }; case 'CLEAR_SELECTION': return { ...state, selectedAgent: null }; default: return state; } }

export function AgentProvider({ children }: { children: ReactNode }) { const [state, dispatch] = useReducer(agentReducer, { agents: [], selectedAgent: null });

return ( <AgentContext.Provider value={{ state, dispatch }}> {children} </AgentContext.Provider> ); }

export function useAgentContext() { const context = useContext(AgentContext); if (!context) { throw new Error('useAgentContext must be used within AgentProvider'); } return context; } ```

React Query を使用したデータ取得

```tsx import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

export function useAgents() { return useQuery({ queryKey: ['agents'], queryFn: async () => { const response = await fetch('/api/agents'); return response.json(); }, staleTime: 5 * 60 * 1000, // 5 分 }); }

export function useCreateAgent() { const queryClient = useQueryClient();

return useMutation({ mutationFn: async (newAgent: CreateAgentInput) => { const response = await fetch('/api/agents', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newAgent), }); return response.json(); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['agents'] }); }, }); } ```

フォーム処理

```tsx import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod';

const agentSchema = z.object({ name: z.string().min(1, '名前は必須です'), type: z.enum(['claude', 'gpt', 'gemini']), description: z.string().optional(), });

type AgentFormData = z.infer;

export function AgentForm({ onSubmit }: { onSubmit: (data: AgentFormData) => void }) { const { register, handleSubmit, formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(agentSchema), });

return (

<input {...register('name')} placeholder="エージェント名" /> {errors.name && {errors.name.message}}

  <select {...register('type')}>
    <option value="claude">Claude</option>
    <option value="gpt">GPT</option>
    <option value="gemini">Gemini</option>
  </select>

  <button type="submit" disabled={isSubmitting}>
    エージェントを作成
  </button>
</form>

); } ```

パフォーマンスの最適化

```tsx import { memo, useMemo, useCallback } from 'react';

// メモ化されたコンポーネント export const AgentList = memo(function AgentList({ agents }: { agents: Agent[] }) { const sortedAgents = useMemo( () => [...agents].sort((a, b) => a.name.localeCompare(b.name)), [agents] );

const handleSelect = useCallback((id: string) => { console.log('選択済み:', id); }, []);

return (

    {sortedAgents.map((agent) => ( <li key={agent.id} onClick={() => handleSelect(agent.id)}> {agent.name} ))}
); }); ```

コメント