Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 0品質スコア 50/100

frontend-react-best-practices

Reactのパフォーマンス最適化ガイドラインを提供するスキルです。Reactコンポーネントの作成・レビュー・リファクタリング時に活用し、最適なレンダリングとバンドル構成を実現します。コンポーネント設計、hooks、メモ化、バンドル最適化に関するタスクで自動的に機能します。

description の原文を見る

React performance optimization guidelines. Use when writing, reviewing, or refactoring React components to ensure optimal rendering and bundle patterns. Triggers on tasks involving React components, hooks, memoization, or bundle optimization.

SKILL.md 本文

React ベストプラクティス

React コンポーネントのパフォーマンス最適化とコンポジション パターン。再レンダリング削減、バンドル最適化、コンポーネント構成、React の一般的な落とし穴の回避に焦点を当てた、6 つのカテゴリにわたる 33 個のルールを含みます。

適用するタイミング

以下の場合にこれらのガイドラインを参照してください:

  • 新しい React コンポーネントを作成する場合
  • パフォーマンスの問題についてコードをレビューする場合
  • 既存の React コードをリファクタリングする場合
  • バンドルサイズを最適化する場合
  • フックとステートを扱う場合

ルール概要

バンドルサイズ最適化 (重大)

bundle-barrel-imports - @rules/bundle-barrel-imports.md

ソースから直接インポートし、barrel ファイルを避ける。

// Bad: ライブラリ全体をロード (200-800ms)
import { Check, X } from "lucide-react";

// Good: 必要な部分のみをロード
import Check from "lucide-react/dist/esm/icons/check";
import X from "lucide-react/dist/esm/icons/x";

bundle-conditional - @rules/bundle-conditional.md

機能が有効な場合のみモジュールをロードする。

useEffect(() => {
  if (enabled && typeof window !== "undefined") {
    import("./heavy-module").then((mod) => setModule(mod));
  }
}, [enabled]);

bundle-preload - @rules/bundle-preload.md

ホバー/フォーカス時にプリロードして体感速度を向上させる。

<button
  onMouseEnter={() => import("./editor")}
  onFocus={() => import("./editor")}
  onClick={openEditor}
>
  Open Editor
</button>

再レンダリング最適化 (中程度)

rerender-functional-setstate - @rules/rerender-functional-setstate.md

安定したコールバックのため関数型 setState を使用する。

// Bad: クロージャが古くなるリスク、items 変更時に再作成される
const addItem = useCallback(
  (item) => {
    setItems([...items, item]);
  },
  [items],
);

// Good: 常に最新のステートを使用し、参照は安定
const addItem = useCallback((item) => {
  setItems((curr) => [...curr, item]);
}, []);

rerender-derived-state-no-effect - @rules/rerender-derived-state-no-effect.md

エフェクト内ではなくレンダリング中にステートを導出する。

// Bad: 追加のステートとエフェクト、追加のレンダリング
const [fullName, setFullName] = useState("");
useEffect(() => {
  setFullName(firstName + " " + lastName);
}, [firstName, lastName]);

// Good: レンダリング中に直接導出
const fullName = firstName + " " + lastName;

rerender-lazy-state-init - @rules/rerender-lazy-state-init.md

高コストの初期値には useState に関数を渡す。

// Bad: 毎回のレンダリングで expensiveComputation() が実行される
const [data] = useState(expensiveComputation());

// Good: 初期レンダリング時のみ実行
const [data] = useState(() => expensiveComputation());

rerender-dependencies - @rules/rerender-dependencies.md

エフェクトの依存関係にはプリミティブ型を使用する。

// Bad: ユーザーのあらゆるフィールド変更で実行される
useEffect(() => {
  console.log(user.id);
}, [user]);

// Good: id 変更時のみ実行
useEffect(() => {
  console.log(user.id);
}, [user.id]);

rerender-derived-state - @rules/rerender-derived-state.md

生の値ではなく導出したブール値にサブスクライブする。

// Bad: ピクセル変更のたびに再レンダリング
const width = useWindowWidth();
const isMobile = width < 768;

// Good: ブール値が変更される場合のみ再レンダリング
const isMobile = useMediaQuery("(max-width: 767px)");

rerender-memo - @rules/rerender-memo.md

高コストの処理をメモ化されたコンポーネントに抽出する。

// Good: loading の場合は計算をスキップ
const UserAvatar = memo(function UserAvatar({ user }) {
  let id = useMemo(() => computeAvatarId(user), [user]);
  return <Avatar id={id} />;
});

function Profile({ user, loading }) {
  if (loading) return <Skeleton />;
  return <UserAvatar user={user} />;
}

rerender-memo-with-default-value - @rules/rerender-memo-with-default-value.md

デフォルト値として非プリミティブ型のプロップを定数に引き上げる。

// Bad: メモ化を破壊 (毎回のレンダリングで新しい関数)
const Button = memo(({ onClick = () => {} }) => ...)

// Good: 安定したデフォルト値
const NOOP = () => {}
const Button = memo(({ onClick = NOOP }) => ...)

rerender-simple-expression-in-memo - @rules/rerender-simple-expression-in-memo.md

シンプルなプリミティブ式を useMemo でラップしない。

// Bad: useMemo のオーバーヘッド > 式のコスト
const isLoading = useMemo(() => a.loading || b.loading, [a.loading, b.loading]);

// Good: 単に計算する
const isLoading = a.loading || b.loading;

rerender-move-effect-to-event - @rules/rerender-move-effect-to-event.md

インタラクションロジックはエフェクトではなくイベントハンドラに置く。

// Bad: エフェクトがテーマ変更で再実行
useEffect(() => {
  if (submitted) post("/api/register");
}, [submitted, theme]);

// Good: ハンドラ内で実行
const handleSubmit = () => post("/api/register");

rerender-transitions - @rules/rerender-transitions.md

緊急度の低い更新に startTransition を使用する。

// Good: ノンブロッキングなスクロール追跡
const handler = () => {
  startTransition(() => setScrollY(window.scrollY));
};

rerender-use-ref-transient-values - @rules/rerender-use-ref-transient-values.md

一時的で頻繁に変わる値には ref を使用する。

// Good: 再レンダリングなし、DOM を直接更新
const lastXRef = useRef(0);
const dotRef = useRef<HTMLDivElement>(null);

useEffect(() => {
  let onMove = (e) => {
    lastXRef.current = e.clientX;
    dotRef.current?.style.transform = `translateX(${e.clientX}px)`;
  };
  window.addEventListener("mousemove", onMove);
  return () => window.removeEventListener("mousemove", onMove);
}, []);

レンダリング パフォーマンス (中程度)

rendering-conditional-render - @rules/rendering-conditional-render.md

数値を含む条件分岐には && ではなく三項演算子を使用する。

// Bad: count が 0 の場合に "0" がレンダリングされる
{
  count && <Badge>{count}</Badge>;
}

// Good: count が 0 の場合は何もレンダリングされない
{
  count > 0 ? <Badge>{count}</Badge> : null;
}

rendering-hoist-jsx - @rules/rendering-hoist-jsx.md

スタティック JSX をコンポーネント外に抽出する。

// Good: 同じ要素を再利用、特に大きな SVG に有効
const skeleton = <div className="animate-pulse h-20 bg-gray-200" />;

function Container({ loading }) {
  return loading ? skeleton : <Content />;
}

rendering-content-visibility - @rules/rendering-content-visibility.md

長いリストには content-visibility を使用する。

.list-item {
  content-visibility: auto;
  contain-intrinsic-size: 0 80px;
}

rendering-animate-svg-wrapper - @rules/rendering-animate-svg-wrapper.md

SVG 要素ではなくラッパー div をアニメーションする (GPU 高速化のため)。

// Good: ハードウェア高速化
<div className="animate-spin">
  <svg>...</svg>
</div>

rendering-svg-precision - @rules/rendering-svg-precision.md

SVGO で SVG 座標の精度を削減する。

npx svgo --precision=1 --multipass icon.svg

rendering-hydration-no-flicker - @rules/rendering-hydration-no-flicker.md

ちらつきを防ぐため、クライアントのみのデータにインラインスクリプトを使用する。

<div id="theme-wrapper">{children}</div>
<script dangerouslySetInnerHTML={{ __html: `
  var theme = localStorage.getItem('theme') || 'light';
  document.getElementById('theme-wrapper').className = theme;
` }} />

rendering-hydration-suppress-warning - @rules/rendering-hydration-suppress-warning.md

予想されるハイドレーション不一致を抑制する。

<span suppressHydrationWarning>{new Date().toLocaleString()}</span>

rendering-client-only - @rules/rendering-client-only.md

ClientOnly とフォールバックを使用してブラウザのみのコンポーネントをレンダリングする。

<ClientOnly fallback={<Skeleton />}>
  {() => <Map />}
</ClientOnly>

rendering-use-hydrated - @rules/rendering-use-hydrated.md

SSR/CSR の不一致に useHydrated を使用する。

let hydrated = useHydrated();
return hydrated ? <Widget /> : <Skeleton />;

rendering-usetransition-loading - @rules/rendering-usetransition-loading.md

手動のローディング状態より useTransition を優先する。

const [isPending, startTransition] = useTransition();

let handleSearch = (value) => {
  startTransition(async () => {
    let data = await fetchResults(value);
    setResults(data);
  });
};

fault-tolerant-error-boundaries - @rules/fault-tolerant-error-boundaries.md

エラーバウンダリーを機能の境界に配置する。

<ErrorBoundary fallback={<SidebarError />}>
  <Sidebar />
</ErrorBoundary>

クライアント パターン (中程度)

client-passive-event-listeners - @rules/client-passive-event-listeners.md

スクロール/タッチには受動的リスナーを使用する。

document.addEventListener("wheel", handler, { passive: true });
document.addEventListener("touchstart", handler, { passive: true });

client-localstorage-schema - @rules/client-localstorage-schema.md

localStorage データをバージョン管理し最小化する。

const VERSION = "v2";

function saveConfig(config: Config) {
  try {
    localStorage.setItem(`config:${VERSION}`, JSON.stringify(config));
  } catch {} // シークレットモード/クォータ超過に対応
}

フック (高)

hooks-limit-useeffect - @rules/hooks-limit-useeffect.md

useEffect は絶対に必要な場合のみ使用する。導出ステートまたはイベントハンドラーを優先する。

// Bad: ステートを導出するために useEffect を使用
let [filtered, setFiltered] = useState(items);
useEffect(() => {
  setFiltered(items.filter((i) => i.active));
}, [items]);

// Good: レンダリング中に導出
let filtered = items.filter((i) => i.active);

// Good: 高コストの場合は useMemo
let filtered = useMemo(() => items.filter((i) => i.active), [items]);

hooks-useeffect-named-functions - @rules/hooks-useeffect-named-functions.md

useEffect では、デバッグと自己ドキュメンテーションの向上のために名前付き関数宣言を使用する。

// Bad: 無名アロー関数
useEffect(() => {
  document.title = title;
}, [title]);

// Good: 名前付き関数
useEffect(
  function syncDocumentTitle() {
    document.title = title;
  },
  [title],
);

// Good: クリーンアップ関数にも名前を付ける
useEffect(function subscribeToOnlineStatus() {
  window.addEventListener("online", handleOnline);
  return function unsubscribeFromOnlineStatus() {
    window.removeEventListener("online", handleOnline);
  };
}, []);

コンポジション パターン (高)

composition-avoid-boolean-props - @rules/composition-avoid-boolean-props.md

動作をカスタマイズするためのブール型プロップを追加しない。代わりにコンポジションを使用する。

// Bad: ブール型プロップの爆発
<Composer isThread isEditing={false} showAttachments />

// Good: 明示的なバリアント
<ThreadComposer channelId="abc" />
<EditComposer messageId="xyz" />

composition-compound-components - @rules/composition-compound-components.md

複雑なコンポーネントを共有コンテキストを持つ複合コンポーネントとして構造化する。

// Good: 複合コンポーネント
<Composer.Provider state={state} actions={actions}>
  <Composer.Frame>
    <Composer.Input />
    <Composer.Footer>
      <Composer.Submit />
    </Composer.Footer>
  </Composer.Frame>
</Composer.Provider>

composition-state-provider - @rules/composition-state-provider.md

ステートをプロバイダー コンポーネントに引き上げてコンポーネント間でアクセスする。

// Good: ステートはプロバイダー内に、内部のどこからでもアクセス可能
<ForwardMessageProvider>
  <Dialog>
    <Composer.Input />
    <MessagePreview /> {/* ステートを読み取り可能 */}
    <ForwardButton /> {/* サブミット呼び出し可能 */}
  </Dialog>
</ForwardMessageProvider>

composition-explicit-variants - @rules/composition-explicit-variants.md

プロップの組み合わせではなく明示的なバリアント コンポーネントを作成する。

// Good: 自己ドキュメント化されたバリアント
function ThreadComposer({ channelId }) {
  return (
    <ThreadProvider channelId={channelId}>
      <Composer.Frame>
        <Composer.Input />
        <AlsoSendToChannelField />
        <Composer.Submit />
      </Composer.Frame>
    </ThreadProvider>
  );
}

composition-children-over-render-props - @rules/composition-children-over-render-props.md

render props ではなく children をコンポジション優先する。render props はデータを返す場合のみ使用する。

// Good: 構造には children
<Card>
  <Card.Header>Title</Card.Header>
  <Card.Body>Content</Card.Body>
</Card>

// OK: データを返す場合は render props
<List renderItem={({ item }) => <Item {...item} />} />

composition-avoid-overabstraction - @rules/composition-avoid-overabstraction.md

厳密な設定プロップを避け、コンポーザブルな children API を優先する。

<Select value="abc" onChange={...}>
  <Option value="abc">ABC</Option>
  <Option value="xyz">XYZ</Option>
</Select>

composition-typescript-namespaces - @rules/composition-typescript-namespaces.md

TypeScript namespace を使用してコンポーネントとその型を組み合わせ、シングルインポートアクセスを実現する。

// components/button.tsx
export namespace Button {
  export type Variant = "solid" | "ghost" | "outline";
  export interface Props {
    variant?: Variant;
    children: React.ReactNode;
  }
}

export function Button({ variant = "solid", children }: Button.Props) {
  // ...
}

// 使用法: シングルインポート
import { Button } from "~/components/button";

<Button variant="ghost">Click</Button>
function wrap(props: Button.Props) { ... }

重要: Namespace は型のみを含め、ランタイムコードは含めない。

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
sergiodxa
リポジトリ
sergiodxa/agent-skills
ライセンス
MIT
最終更新
不明

Source: https://github.com/sergiodxa/agent-skills / ライセンス: MIT

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: sergiodxa · sergiodxa/agent-skills · ライセンス: MIT