typescript-react について
React の作業に TypeScript Style Guide の規約を適用するスキルです。プロジェクトの慣習を尊重しつつ、コンポーネント構成、Props、状態、データフローを案内します。
主な機能
- 01リポジトリ規約の優先確認
- 02コンテナと UI コンポーネントの指針
- 03Props と状態の推奨事項
- 04URL とグローバル状態の指針
- 05データ取得の境界
活用シーン
- 01React 機能とコンポーネントの構成
- 02Props を初期状態にするパターンの確認
- 03アプリケーション状態の配置検討
- 04機能内のデータ取得計画
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ mkosir/ typescript-style-guide --skill typescript-reactインストール後、Claude Code で/typescript-reactを入力して読み込まれたか確認します。
詳細
React
現在のタスクにおいて、TypeScript Style Guide の React 規約を適用します。
ワークフロー
- 利用側のリポジトリにおける React、フレームワーク、状態管理の規約を確認します。
- この意見に基づくガイダンスより、リポジトリで明示されている規約を優先します。
- タスクに関連するガイダンスのみを適用、レビュー、または説明します。
- コンポーネントや状態の設計がアプリケーションのコンテキストに依存する場合は、重要なトレードオフを示します。
適用範囲
- TypeScript、React、ESLint が自動的に強制できるチェックは、それぞれに任せます。
- このガイドが適用されているというだけで、無関係なコンポーネントや状態を再設計しないでください。
関連するガイダンス
関数
関数設計の詳しいガイダンスについては、利用可能な場合は typescript-functions を使用してください。
付録 - React
React コンポーネントとフックも関数であるため、それぞれに対応する関数の規約が適用されます。
Props から State への初期化
一般に、props を初期状態として使用することは避けてください。props が変更されても state は更新されず、追跡しにくいバグや意図しない副作用が発生したり、テストが難しくなったりする可能性があります。
prop を初期状態として使用する正当なユースケースがある場合は、prop の名前に initial を接頭辞として付ける必要があります(例:initialProduct、initialSort など)。
// ❌ Avoid using props to state
type FooProps = {
productName: string;
userId: string;
};
export const Foo = ({ productName, userId }: FooProps) => {
const [productName, setProductName] = useState(productName);
...
// ✅ Use prop prefix `initial` when there is a rationale for it
type FooProps = {
initialProductName: string;
userId: string;
};
export const Foo = ({ initialProductName, userId }: FooProps) => {
const [productName, setProductName] = useState(initialProductName);
...
Props の型
// ❌ Avoid using React.FC type
type FooProps = {
name: string;
score: number;
};
export const Foo: React.FC<FooProps> = ({ name, score }) => {
// ✅ Use props argument with type
type FooProps = {
name: string;
score: number;
};
export const Foo = ({ name, score }: FooProps) => {...
コンポーネントの種類
コンテナー
- すべてのコンテナーコンポーネントには、接尾辞として「Container」または「Page」を付けます(
[ComponentName]Container|Page)。コンポーネントが実際のウェブページであることを示す場合は、「Page」の接尾辞を使用します。 - 各機能にはコンテナーコンポーネントがあります(
AddUserContainer.tsx、EditProductContainer.tsx、ProductsPage.tsxなど)。 - ビジネスロジックを含みます。
- API と連携します。
- 構成:
ProductsPage/ ├─ api/ │ └─ useGetProducts/ ├─ components/ │ └─ ProductItem/ ├─ utils/ │ └─ filterProductsByType/ └─ index.tsx
UI - 機能
- 機能要件を満たすために設計された、表示を担うコンポーネントです。
- コンテナーコンポーネントのフォルダー内に配置します。
- 可能な限り関数の規約に従います。
- API 連携は行いません。
- 構成:
ProductItem/ ├─ index.tsx ├─ ProductItem.stories.tsx └─ ProductItem.test.tsx
UI - デザインシステム
- コードベース全体で使用される、グローバルに再利用可能なコンポーネントまたは共有コンポーネントです。
- 構成:
Button/ ├─ index.tsx ├─ Button.stories.tsx └─ Button.test.tsx
データの保存と受け渡し
-
オブジェクト全体を渡すのではなく、子コンポーネントに必要な props だけを渡します。
-
特にフィルタリングやソートなどでは、URL に状態を保存する方法を活用します。
-
URL の状態をローカル状態と同期しないでください。
-
props、URL、または子コンポーネントの構成を使って、データをシンプルに受け渡すことを検討してください。グローバル状態(Zustand、Context)の使用は最後の手段とします。
-
コンポーネント同士を連携させる必要がある場合は、React の複合コンポーネントを使用します(
menu、accordion、navigation、tabs、listなど)。
複合コンポーネントは、必ず次のようにエクスポートします。// PriceList.tsx const PriceListRoot = ({ children }) => <ul>{children}</ul>; const PriceListItem = ({ title, amount }) => <li>Name: {name} - Amount: {amount}<li/>; // ❌ export const PriceList = { Container: PriceListRoot, Item: PriceListItem, }; // ❌ PriceList.Item = Item; export default PriceList; // ✅ export const PriceList = PriceListRoot as typeof PriceListRoot & { Item: typeof PriceListItem; }; PriceList.Item = PriceListItem; // App.tsx import { PriceList } from "./PriceList"; <PriceList> <PriceList.Item title="Item 1" amount={8} /> <PriceList.Item title="Item 2" amount={12} /> </PriceList>; -
UI コンポーネントは派生状態を表示し、イベントを送信するだけにします(ビジネスロジックは含めません)。
-
多くのプログラミング言語と同様に、関数の引数は次の関数へ、さらにその次へと渡すことができます。
React コンポーネントも同じなので、props のバケツリレーを問題視する必要はありません。
アプリケーションの成長に伴い、props のバケツリレーが本当に問題になった場合は、親コンポーネントのレンダリングメソッドやローカル状態のリファクタリング、またはコンポジションを試してください。 -
データの取得はコンテナーコンポーネントでのみ行えます。
-
サーバー状態ライブラリの使用を推奨します(TanStack Query、Apollo Client など)。
-
グローバル状態にクライアント状態ライブラリを使用することは推奨しません。
themeModeやPermissionsのように、アプリケーション全体で本当にグローバルであるべきものなのか、それともサーバー状態(例:/meエンドポイントから取得するユーザー設定)として扱えるのかを再検討してください。グローバル状態が本当に必要な場合は、Zustand または Context を使用してください。