mcpField
R
react-core

react-core

github.com/bobmatnyc開発78209 回インストール16 週間前に更新
リポジトリ

react-core について

React の基礎を扱うリファレンススキルです。React コンポーネントを作る開発者や、関連スキルの前提知識を整える用途に向け、状態、描画、フォームなどの基本パターンをまとめています。

主な機能

  1. 01コンポーネント、JSX、props、状態
  2. 02コアフックと使い方
  3. 03コンポジションとカスタムフック
  4. 04条件付き描画とリスト描画
  5. 05制御されたフォーム入力
  6. 06よくある誤用と回避策

活用シーン

  1. 01コンポーネントの作成とデータ受け渡し
  2. 02課題に応じたコアフックの選択
  3. 03条件付き UI とリストの描画
  4. 04状態に基づくフォーム入力の実装

インストール

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

$npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill react-core

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

同梱ファイルmetadata.json

詳細

React のコアとなる基礎

概要

React の一般的な基礎を網羅した標準的なリファレンスです。このスキルでは、すべての React アプリケーションに共通する構成要素である、コンポーネントと JSX、props と state、コアフック、コンポジションパターン、条件付きレンダリングとリストレンダリング、制御された入力を扱います。これは、React のコア知識を前提とするエコシステムスキル(スタイリング、データ取得、状態管理、デプロイ)の基盤となる「React に依存する」ための参照先です。

このスキルは基礎に焦点を絞ります。高度なフックのコンポジション(SWR を使ったカスタムフック、デバウンス付きコンテキスト、メモ化されたプロバイダー)については、関連する react-hooks-composition スキルを使用してください。複雑な UI フローを明示的な有限状態機械としてモデル化する場合は、関連する react-state-machine スキルを使用してください。

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

次のような場合にこのスキルを利用してください:

  • コンポーネントの作成、props の接続、ローカル状態の管理
  • 特定の問題に適したコアフックの選択
  • リストや条件付き UI のレンダリング
  • 制御されたフォーム入力の実装
  • 別のエコシステムスキルが依存する React の基礎を確立する

コンポーネントと JSX

React コンポーネントは JSX を返す関数です。コンポーネント名には PascalCase を使用します。単一のルートノードを返すか、フラグメント(<>...</>)で兄弟要素を囲みます。

type GreetingProps = {
  name: string;
};

function Greeting({ name }: GreetingProps) {
  return (
    <>
      <h1>Hello, {name}</h1>
      <p>Welcome back.</p>
    </>
  );
}

JSX では {} の中に式を埋め込みます。属性には camelCase(className、onClick、htmlFor)を使用します。JSX は UI の記述を返し、React はそれを DOM と照合して調整します。

Props と State

Props は親から子へデータを渡すもので、子の内部では読み取り専用です。State は、コンポーネントが所有し、時間とともに変更するデータを保持します。

import { useState } from 'react';

function Counter({ step = 1 }: { step?: number }) {
  const [count, setCount] = useState(0);

  return (
    <button onClick={() => setCount((prev) => prev + step)}>
      Count: {count}
    </button>
  );
}

Props と state は不変として扱います。state はセッターを使って更新し、次の値が前の値から導かれる場合は、関数型の更新処理(setCount(prev => prev + 1))を優先してください。

コアフックの概要

フックはコンポーネントまたはカスタムフックのトップレベルでのみ呼び出してください。条件分岐、ループ、ネストされた関数の中では呼び出さないでください。このルールにより、レンダー間でフックの呼び出し順が安定します。

useState — コンポーネントのローカル状態

値とセッターを保持します。値が変わるとコンポーネントを再レンダリングします。

const [open, setOpen] = useState(false);
useEffect — 外部システムとの同期

レンダー後に実行され、サブスクリプション、タイマー、データ取得、手動での DOM 操作などの副作用を実行します。依存配列によってエフェクトが再実行されるタイミングを制御します。サブスクリプションを解除するには、クリーンアップ関数を返します。

import { useEffect, useState } from 'react';

function WindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const onResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, []); // empty deps: subscribe once on mount, clean up on unmount

  return <span>{width}px</span>;
}
useRef — レンダーをまたいで保持される可変値

再レンダリングを引き起こさずに可変値を保持します。よくある用途は、DOM ノードへの参照や、レンダーをまたいで値を保持すること(タイマー ID、以前の値)です。

import { useRef, useEffect } from 'react';

function AutoFocusInput() {
  const inputRef = useRef<HTMLInputElement>(null);
  useEffect(() => inputRef.current?.focus(), []);
  return <input ref={inputRef} />;
}
useMemo — コストの高い計算をキャッシュ

依存関係が変わった場合にのみ値を再計算します。実際にコストの高い計算や、メモ化された子コンポーネントに渡す参照の同一性を安定させる場合に使用してください。

const sorted = useMemo(() => items.slice().sort(compare), [items]);
useCallback — 関数の参照を安定させる

依存関係が等しい間は、レンダーをまたいで同じ関数インスタンスを返します。安定したコールバックをメモ化された子コンポーネントや、エフェクトの依存配列に渡します。

const handleSelect = useCallback((id: string) => onSelect(id), [onSelect]);
useContext — props のバケツリレーなしで共有状態を読み取る

ツリー内の上位で提供されたコンテキストの現在の値を読み取ります。

import { createContext, useContext } from 'react';

const ThemeContext = createContext<'light' | 'dark'>('light');

function ThemedLabel() {
  const theme = useContext(ThemeContext);
  return <span className={theme}>Themed</span>;
}

不要なコンシューマーの再レンダリングを防ぐメモ化されたプロバイダーパターンについては、react-hooks-composition を参照してください。

コンポジションパターン

設定よりもコンポジションを優先します。children を通してコンテンツを渡し、props を通して振る舞いを渡します。

function Card({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <section className="card">
      <h2>{title}</h2>
      <div className="card-body">{children}</div>
    </section>
  );
}

// Usage
<Card title="Profile">
  <Avatar />
  <p>Bio text</p>
</Card>;

共有ロジックはコンポーネント間でコピーするのではなく、カスタムフック(useSomething)に切り出します。コンポーネントは小さく、単一の役割に絞ってください。

条件付きレンダリングとリストレンダリング

要素の有無には && を、どちらか一方を表示する場合には三項演算子を使って条件付きでレンダリングします。リストは map でレンダリングし、各項目には、その識別情報に基づく安定した key を指定してください(順序が変わる可能性がある場合は、配列のインデックスを使わないでください)。

function TodoList({ todos }: { todos: { id: string; text: string; done: boolean }[] }) {
  if (todos.length === 0) return <p>No todos yet.</p>;

  return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>
          {todo.done ? <s>{todo.text}</s> : todo.text}
        </li>
      ))}
    </ul>
  );
}

制御された入力

制御された入力は state から値を取得し、onChange を通して変更を通知します。state が唯一の信頼できる情報源です。

import { useState } from 'react';

function NameField() {
  const [name, setName] = useState('');

  return (
    <label>
      Name
      <input
        value={name}
        onChange={(event) => setName(event.target.value)}
      />
    </label>
  );
}

避けるべきアンチパターン

❌ やってはいけないこと:状態を直接変更する

直接変更するとセッターが実行されないため、React は再レンダリングしません。

// BAD: mutates the array in place; React sees the same reference
function addItem(items: string[], next: string) {
  items.push(next);
  setItems(items);
}
// GOOD: create a new array so the reference changes
function addItem(items: string[], next: string) {
  setItems([...items, next]);
}
❌ やってはいけないこと:条件付きでフックを呼び出す

条件付きでフックを呼び出すと、React が依存する安定した呼び出し順序が崩れます。

// BAD: hook call order changes between renders
function Profile({ id }: { id?: string }) {
  if (id) {
    const data = useUser(id); // conditional hook call
    return <span>{data.name}</span>;
  }
  return null;
}
// GOOD: call the hook unconditionally; branch on its result
function Profile({ id }: { id?: string }) {
  const data = useUser(id); // useUser must accept an undefined id (no fetch / returns null) so the hook is always called
  if (!id || !data) return null;
  return <span>{data.name}</span>;
}
❌ やってはいけないこと:並べ替え可能なリストのキーに配列インデックスを使う

インデックスをキーにすると、項目が移動したときに React が状態を誤った項目に紐付ける原因になります。

// BAD: index key breaks on reorder/insert/delete
{items.map((item, i) => <Row key={i} item={item} />)}
// GOOD: stable identity key
{items.map((item) => <Row key={item.id} item={item} />)}

関連するスキルを使う場面

  • react-hooks-composition:高度なカスタムフックの構成。SWR を利用したデータ取得、2 つのローディング状態を備えたデバウンス検索、メモ化されたコンテキストプロバイダー、再利用可能な非同期状態フックが対象です。
  • react-state-machine:複雑なフロー(複数ステップのフォーム、メディアプレーヤー、アニメーション付きモーダルなど)で、表現不可能な状態を作る必要がある場合の、XState v5 を使った明示的な有限状態機械のモデリングです。
  • react-advanced:React 19 のプラットフォーム機能とレンダリングアーキテクチャ。React Compiler(自動メモ化)、並行レンダリング、use() フック、Actions、仮想化、コード分割、RSC 境界が対象です。

ベストプラクティスのまとめ

  1. コンポーネントは JSX を返す:名前は PascalCase にし、単一のルート要素またはフラグメントを返します。
  2. Props は読み取り専用:データを渡し、共有する状態は必要に応じて上位に移動します。
  3. 状態はイミュータブルに更新する:セッターを使い、関数型アップデーターを優先します。
  4. フックはトップレベルでのみ呼び出す:条件付きでフックを呼び出してはいけません。
  5. エフェクトは外部システムとの同期に使う:依存関係で対象範囲を定め、サブスクリプションをクリーンアップします。
  6. 意図的にメモ化する:処理コストが高い場合や安定した同一性が必要な場合に useMemo/useCallback を適用し、デフォルトでは使いません。
  7. 安定したキーを使う:リストのキーには配列インデックスではなく、項目の同一性を使います。
  8. 制御された入力を使う:状態を唯一の信頼できる情報源とします。

参考資料

コメント