Advanced (更新: 2026/6/2)

Claude CodeでReact Error Boundaryを安全に実装する実務ガイド

ReactのError BoundaryをClaude Codeで安全に実装する実務ガイド。捕捉範囲、配置、リセット、ログ、テストまで解説。

Claude CodeでReact Error Boundaryを安全に実装する実務ガイド

Reactアプリで一番まずい障害は、ひとつのウィジェットの例外で画面全体が真っ白になることです。Claude Codeに「エラー処理を入れて」と頼むだけだと、try/catchを数か所に足すだけで終わり、Reactのレンダー中に起きる例外は捕まらないまま残りがちです。

この記事では、ReactのError BoundaryをClaude Codeで実装するときの実務手順をまとめます。Error Boundaryは、子コンポーネントのレンダー中に起きた例外を受け止め、壊れた部分の代わりにフォールバックUIを表示する境界です。日本語で言えば「画面の防火扉」です。火元を消す仕組みではなく、燃え広がりを止め、ユーザーに次の行動を示す仕組みだと考えると設計しやすくなります。

Masaが管理画面のダッシュボードで試したとき、最初はページ全体を1つのError Boundaryで囲んだだけでした。たしかに白画面は減りましたが、グラフ1つの失敗でページ全体が「エラーです」になり、調査ログにはメールアドレス入りのURLが残りました。配置、リセット、ログの粒度までプロンプトに含めるように変えると、Claude Codeの出力はレビューしやすくなりました。

React公式情報で前提を固める

まずClaude Codeに渡す前提を固定します。React公式のComponentリファレンスでは、static getDerivedStateFromErrorでフォールバック表示用の状態を更新し、componentDidCatchでログ送信などの副作用を扱う、という役割分担が説明されています。さらに公式のerror-boundaries lint解説では、レンダー中の例外は通常のtry/catchでは捕まらず、Error Boundaryで扱うべきだと整理されています。

ここで重要なのは「Error Boundaryを置けば全部安全」ではないことです。ReactのError Boundaryが捕捉できるのは、子コンポーネントがレンダー、ライフサイクル、フック実行の流れで投げた例外です。一方で、クリックハンドラ、setTimeoutrequestAnimationFrame、通常のPromise失敗、サーバーサイドレンダリング、Error Boundary自身の例外は別に扱う必要があります。

Claude Codeに最初からこの表を渡すと、危ない実装を避けやすくなります。

場所Error Boundaryで捕捉実務での扱い
子コンポーネントのレンダー中の例外はい境界でフォールバックUIを表示し、ログを送る
useMemoやカスタムフック実行中の例外多くの場合はい期待される失敗は事前に検証し、予期せぬ例外だけ境界へ
クリックや送信ボタンのイベントハンドラいいえハンドラ内でtry/catchし、必要なら状態経由で境界へ投げ直す
setTimeoutや通常の非同期処理いいえPromiseの失敗を明示的に処理し、ユーザー操作の再試行を用意する
サーバーサイドレンダリングいいえフレームワーク側のエラーページ、ログ、HTTPステータスで扱う
Error Boundary自身の例外いいえ境界のフォールバックUIは依存を少なくし、さらに上位境界を置く
flowchart TD
  A["子コンポーネントがレンダー中に例外を投げる"] --> B["最寄りのError Boundary"]
  B --> C["ユーザー向けフォールバックUI"]
  B --> D["PIIを除いたエラーログ"]
  E["クリック処理やsetTimeoutの例外"] --> F["ハンドラで処理するか状態経由で境界へ渡す"]
  F --> B

配置はルート単位と部品単位を分ける

Error Boundaryは多ければよいものではありません。全画面に1つだけだと影響範囲が広すぎますが、ボタンやアイコンまで細かく囲むと、どこで何が壊れたのか分かりにくくなります。Claude Codeには「境界を置く場所」と「置かない場所」を明示します。

ルート単位の境界は、ページ遷移ごとの安全網です。ダッシュボード、設定画面、請求画面、記事編集画面のように、画面全体の責務が変わる場所に置きます。ルートが変わったら境界をリセットし、古い画面の失敗状態を次の画面へ持ち越さないようにします。

部品単位の境界は、ページの中でも独立して壊れてよい領域に置きます。例として、売上グラフ、通知パネル、Markdownプレビュー、外部API由来のおすすめ枠があります。逆に、フォームの1つの入力欄、通常のボタン、見出し、アイコンだけを個別に囲むのは過剰です。

実務で使いやすい判断基準は次の3つです。

  • その部分が壊れても、ユーザーが他の作業を続けられるか
  • その部分だけ再読み込み、再取得、初期化できるか
  • ログを見たときに、機能名やルート名で原因を切り分けられるか

Claude Codeのテスト戦略と合わせて考えると、境界の粒度はテスト単位にもなります。ユーザーが再試行する範囲と、テストが壊れた範囲が一致していると、運用で迷いません。

コピーして使えるError Boundary本体

以下はReact + TypeScriptでそのまま使える最小構成です。関数コンポーネント全盛でも、React公式が説明している通り、Error Boundary本体はクラスコンポーネントで実装します。アプリ全体に1つだけ置く共通部品として作れば、普段の画面開発は関数コンポーネントのままで問題ありません。

// src/components/error-boundary/ErrorBoundary.tsx
import { Component, ErrorInfo, ReactNode } from "react";

export type ErrorBoundaryFallbackProps = {
  error: Error;
  resetErrorBoundary: () => void;
};

type ErrorBoundaryProps = {
  children: ReactNode;
  fallback?: ReactNode | ((props: ErrorBoundaryFallbackProps) => ReactNode);
  onError?: (error: Error, info: ErrorInfo) => void;
  onReset?: () => void;
  resetKeys?: ReadonlyArray<unknown>;
};

type ErrorBoundaryState = {
  error: Error | null;
};

function normalizeError(value: unknown): Error {
  if (value instanceof Error) return value;
  return new Error(typeof value === "string" ? value : "Unknown render error");
}

function changedArray(
  previous: ReadonlyArray<unknown> = [],
  next: ReadonlyArray<unknown> = [],
): boolean {
  return (
    previous.length !== next.length ||
    previous.some((item, index) => !Object.is(item, next[index]))
  );
}

export class ErrorBoundary extends Component<
  ErrorBoundaryProps,
  ErrorBoundaryState
> {
  state: ErrorBoundaryState = { error: null };

  static getDerivedStateFromError(error: unknown): ErrorBoundaryState {
    return { error: normalizeError(error) };
  }

  componentDidCatch(error: Error, info: ErrorInfo) {
    this.props.onError?.(normalizeError(error), info);
  }

  componentDidUpdate(previousProps: ErrorBoundaryProps) {
    if (
      this.state.error &&
      changedArray(previousProps.resetKeys, this.props.resetKeys)
    ) {
      this.resetErrorBoundary();
    }
  }

  resetErrorBoundary = () => {
    this.props.onReset?.();
    this.setState({ error: null });
  };

  render() {
    if (!this.state.error) return this.props.children;

    if (typeof this.props.fallback === "function") {
      return this.props.fallback({
        error: this.state.error,
        resetErrorBoundary: this.resetErrorBoundary,
      });
    }

    if (this.props.fallback) return this.props.fallback;

    return (
      <section role="alert" aria-labelledby="error-boundary-title">
        <h2 id="error-boundary-title">Something went wrong</h2>
        <p>Please retry. If the problem continues, contact support.</p>
        <button type="button" onClick={this.resetErrorBoundary}>
          Try again
        </button>
      </section>
    );
  }
}

この実装では、fallbackをReactNodeでも関数でも渡せます。関数にしておくと、エラー内容を見て「再試行」「アプリを再読み込み」「サポートへ連絡」を出し分けられます。ただし、ユーザー向けUIにerror.stackやAPIレスポンス全文を出してはいけません。画面には短い説明、操作ボタン、問い合わせ用のイベントID程度に留めます。

ユーザー向けフォールバックUIとリセット

フォールバックUIは「申し訳ありません」だけでは足りません。ユーザーが次に何をすればよいか、作業内容が失われる可能性があるか、再試行してよいかを伝えます。特にチャンク読み込み失敗のようなデプロイ直後のエラーでは、再読み込みボタンが有効です。

// src/components/error-boundary/AppErrorFallback.tsx
import type { ErrorBoundaryFallbackProps } from "./ErrorBoundary";

export function AppErrorFallback({
  error,
  resetErrorBoundary,
}: ErrorBoundaryFallbackProps) {
  const reloadRecommended =
    /ChunkLoadError|Loading chunk|dynamically imported module/i.test(
      error.message,
    );

  return (
    <section
      role="alert"
      aria-labelledby="app-error-title"
      className="error-fallback"
    >
      <div>
        <p className="error-fallback__eyebrow">This section stopped working</p>
        <h2 id="app-error-title">We could not render this part of the page.</h2>
        <p>
          Your account data was not changed. Retry this section first, then
          reload the app if the same message appears again.
        </p>
      </div>

      <div className="error-fallback__actions">
        <button type="button" onClick={resetErrorBoundary}>
          Try again
        </button>
        {reloadRecommended ? (
          <button type="button" onClick={() => window.location.reload()}>
            Reload app
          </button>
        ) : null}
      </div>
    </section>
  );
}
/* src/components/error-boundary/error-fallback.css */
.error-fallback {
  border: 1px solid #d7dde8;
  border-radius: 8px;
  padding: 16px;
  background: #fff;
  color: #1f2937;
}

.error-fallback__eyebrow {
  margin: 0 0 4px;
  color: #6b7280;
  font-size: 0.875rem;
}

.error-fallback h2 {
  margin: 0 0 8px;
  font-size: 1.125rem;
}

.error-fallback__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}

リセットでよくある失敗は、境界の状態だけを消して、壊れた子コンポーネントの入力を変えないことです。同じprops、同じ壊れたキャッシュ、同じ例外が残っていれば、再試行ボタンを押してもすぐ同じフォールバックに戻ります。ルート遷移、検索条件、再取得キー、ユーザーIDなどをresetKeysに入れ、入力が変わったときだけ境界を自動復帰させるのが安全です。

ルート単位と部品単位の実装例

React Routerを使う場合、ルート境界はページ要素を包む薄いラッパーにします。ここではlocation.keyresetKeysに入れ、履歴遷移ごとに古いエラー状態をリセットします。Next.jsやRemixのようなフレームワークでは専用のエラーファイルやルート境界がありますが、考え方は同じです。

// src/AppRoutes.tsx
import { lazy, ReactNode, Suspense } from "react";
import {
  createBrowserRouter,
  RouterProvider,
  useLocation,
} from "react-router-dom";
import { ErrorBoundary } from "./components/error-boundary/ErrorBoundary";
import { AppErrorFallback } from "./components/error-boundary/AppErrorFallback";
import { currentErrorContext, reportReactError } from "./lib/error-reporting";
import { Layout } from "./routes/Layout";

const DashboardPage = lazy(() => import("./routes/DashboardPage"));
const SettingsPage = lazy(() => import("./routes/SettingsPage"));

function RouteBoundary({
  children,
  feature,
}: {
  children: ReactNode;
  feature: string;
}) {
  const location = useLocation();

  return (
    <ErrorBoundary
      resetKeys={[location.key]}
      fallback={(props) => <AppErrorFallback {...props} />}
      onError={(error, info) => {
        void reportReactError(
          error,
          info.componentStack,
          currentErrorContext(feature),
        );
      }}
    >
      <Suspense fallback={<p>Loading...</p>}>{children}</Suspense>
    </ErrorBoundary>
  );
}

const router = createBrowserRouter([
  {
    path: "/",
    element: <Layout />,
    children: [
      {
        path: "dashboard",
        element: (
          <RouteBoundary feature="dashboard">
            <DashboardPage />
          </RouteBoundary>
        ),
      },
      {
        path: "settings",
        element: (
          <RouteBoundary feature="settings">
            <SettingsPage />
          </RouteBoundary>
        ),
      },
    ],
  },
]);

export function AppRoutes() {
  return <RouterProvider router={router} />;
}

部品単位の境界は、外部データ、重い可視化、プラグイン、ユーザー入力のプレビューなどに置きます。たとえばMarkdownプレビューが壊れても、編集フォームは残すべきです。請求ページでは支払いフォーム全体を囲むより、補助的なおすすめプランやグラフを個別に囲むほうが安全です。決済ボタンの失敗はError Boundaryではなく、イベントハンドラで処理してユーザーに具体的な失敗理由を返します。

非同期とイベントハンドラは別に扱う

クリック処理や送信処理の失敗は、Error Boundaryが自動では捕捉しません。予期される失敗、たとえば入力エラー、認証切れ、在庫不足、レート制限は、フォームやトーストで通常の状態として見せます。予期しない例外だけ境界へ渡すと、画面の安全網として機能します。

// src/components/error-boundary/useAsyncBoundary.ts
import { useCallback, useState } from "react";

function toError(value: unknown): Error {
  if (value instanceof Error) return value;
  return new Error(typeof value === "string" ? value : "Unknown async error");
}

export function useAsyncBoundary() {
  const [error, setError] = useState<Error | null>(null);

  if (error) {
    throw error;
  }

  return useCallback((value: unknown) => {
    setError(toError(value));
  }, []);
}
// src/components/settings/SaveButton.tsx
import { useState } from "react";
import { useAsyncBoundary } from "../error-boundary/useAsyncBoundary";

type SaveButtonProps = {
  onSave: () => Promise<void>;
};

export function SaveButton({ onSave }: SaveButtonProps) {
  const [pending, setPending] = useState(false);
  const throwToBoundary = useAsyncBoundary();

  async function handleClick() {
    setPending(true);

    try {
      await onSave();
    } catch (error) {
      throwToBoundary(error);
    } finally {
      setPending(false);
    }
  }

  return (
    <button type="button" disabled={pending} onClick={handleClick}>
      {pending ? "Saving..." : "Save"}
    </button>
  );
}

Claude Codeには「非同期失敗をすべてError Boundaryに送るな」と明示します。たとえばバリデーションエラーまで境界に送ると、ユーザーは入力を直せず、ページの一部が壊れたように見えます。境界へ送るのは、想定外の例外、壊れたレスポンス、表示コンポーネントの不整合などです。

PIIを漏らさないログ設計

componentDidCatchはログ送信に向いていますが、送る内容を絞らないと危険です。PIIは個人を特定できる情報のことで、メールアドレス、氏名、電話番号、アクセストークン、住所、カード番号、問い合わせ本文などが含まれます。ReactのcomponentStackは有用ですが、エラーメッセージやURLにPIIが混ざることがあります。

ログには、機能名、リリース番号、ルートのパス、エラー名、短いメッセージ、コンポーネントスタックを送ります。クエリ文字列、フォーム入力値、Cookie、Authorizationヘッダー、APIレスポンス全文は送らない方針にします。

// src/lib/error-reporting.ts
type ClientErrorContext = {
  route: string;
  release: string;
  feature?: string;
  userHash?: string;
};

const REDACTIONS: Array<[RegExp, string]> = [
  [/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi, "[redacted-email]"],
  [/\b(?:\d[ -]*?){13,19}\b/g, "[redacted-number]"],
  [/\b(token|secret|password|authorization)=([^&\s]+)/gi, "$1=[redacted]"],
  [/\bBearer\s+[A-Za-z0-9._~+/=-]+/gi, "Bearer [redacted]"],
];

export function redactText(value: string | undefined): string | undefined {
  if (!value) return value;

  return REDACTIONS.reduce(
    (text, [pattern, replacement]) => text.replace(pattern, replacement),
    value,
  );
}

export function currentErrorContext(feature?: string): ClientErrorContext {
  const env = (import.meta as unknown as {
    env?: Record<string, string | undefined>;
  }).env;

  return {
    route: typeof window === "undefined" ? "server" : window.location.pathname,
    release: env?.VITE_APP_VERSION ?? "dev",
    feature,
  };
}

export async function reportReactError(
  error: Error,
  componentStack: string | undefined,
  context: ClientErrorContext,
) {
  const payload = {
    name: redactText(error.name) ?? "Error",
    message: redactText(error.message) ?? "Unknown error",
    stack: redactText(error.stack),
    componentStack: redactText(componentStack),
    route: context.route,
    release: context.release,
    feature: context.feature,
    userHash: context.userHash,
  };

  const body = JSON.stringify(payload);

  if (typeof navigator !== "undefined" && navigator.sendBeacon) {
    const sent = navigator.sendBeacon(
      "/api/client-errors",
      new Blob([body], { type: "application/json" }),
    );
    if (sent) return;
  }

  await fetch("/api/client-errors", {
    method: "POST",
    headers: { "content-type": "application/json" },
    credentials: "omit",
    keepalive: true,
    body,
  });
}

本番では、サーバー側でも同じ方針で再度マスクします。ブラウザ側のマスクだけに頼ると、将来の変更で漏れたときに止められません。Claude Codeへのプロンプトにも「クライアントとサーバーの両方でマスク」「URLはpathnameのみ」「ユーザーIDはハッシュ化済みの値だけ」と書いておきます。

テストで境界の振る舞いを固定する

Error Boundaryは壊れたときの部品なので、テストなしで入れると安心材料になりません。最低限、フォールバックが表示されること、ログ関数が呼ばれること、再試行で子コンポーネントへ戻れることを確認します。

// src/components/error-boundary/ErrorBoundary.test.tsx
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import "@testing-library/jest-dom/vitest";
import { ReactNode, useState } from "react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { ErrorBoundary } from "./ErrorBoundary";

function Bomb({ shouldThrow }: { shouldThrow: boolean }) {
  if (shouldThrow) {
    throw new Error("profile widget crashed");
  }

  return <p>Profile loaded</p>;
}

function RetryHarness({ onError }: { onError: ReturnType<typeof vi.fn> }) {
  const [broken, setBroken] = useState(true);

  return (
    <ErrorBoundary
      onError={onError}
      fallback={({ resetErrorBoundary }) => (
        <button
          type="button"
          onClick={() => {
            setBroken(false);
            resetErrorBoundary();
          }}
        >
          Retry profile
        </button>
      )}
    >
      <Bomb shouldThrow={broken} />
    </ErrorBoundary>
  );
}

function StaticFallback({ children }: { children: ReactNode }) {
  return (
    <ErrorBoundary fallback={<p>Could not load this panel.</p>}>
      {children}
    </ErrorBoundary>
  );
}

describe("ErrorBoundary", () => {
  let consoleErrorSpy: ReturnType<typeof vi.spyOn>;

  beforeEach(() => {
    consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
  });

  afterEach(() => {
    consoleErrorSpy.mockRestore();
  });

  it("renders fallback UI when a child throws", () => {
    render(
      <StaticFallback>
        <Bomb shouldThrow />
      </StaticFallback>,
    );

    expect(screen.getByText("Could not load this panel.")).toBeInTheDocument();
  });

  it("calls onError with the thrown error and component stack", () => {
    const onError = vi.fn();

    render(<RetryHarness onError={onError} />);

    expect(onError).toHaveBeenCalledTimes(1);
    expect(onError.mock.calls[0][0].message).toBe("profile widget crashed");
    expect(onError.mock.calls[0][1].componentStack).toContain("Bomb");
  });

  it("can reset and render children again", async () => {
    const user = userEvent.setup();
    const onError = vi.fn();

    render(<RetryHarness onError={onError} />);
    await user.click(screen.getByRole("button", { name: "Retry profile" }));

    expect(screen.getByText("Profile loaded")).toBeInTheDocument();
  });
});

検証コマンドもClaude Codeに実行させます。プロジェクトに合わせてtypechecktestのスクリプト名は調整してください。

npm install -D vitest @testing-library/react @testing-library/user-event @testing-library/jest-dom jsdom
npm run typecheck
npx vitest run src/components/error-boundary/ErrorBoundary.test.tsx
npm run build

Claude Codeに渡す安全なプロンプト

Claude Codeへ頼むときは、実装範囲、捕捉範囲、ログ禁止事項、検証コマンドをまとめて渡します。曖昧な依頼にすると、console.error(error)や画面へのerror.message直出しが混ざりやすくなります。

React + TypeScriptアプリにError Boundaryを追加してください。

制約:
- React公式のError Boundary前提に合わせること。
- 子コンポーネントのレンダー例外を捕捉し、イベントハンドラや通常の非同期失敗は別処理にすること。
- 共通のErrorBoundaryクラス、ユーザー向けfallback UI、PIIをマスクするreportReactErrorを実装すること。
- route-level boundaryはルート遷移でresetKeysを変えること。
- component-level boundaryはDashboardChart、MarkdownPreview、RecommendationPanelのような独立領域だけに置くこと。
- error.stack、クエリ文字列、フォーム入力値、Authorizationヘッダー、Cookieをログ送信しないこと。
- Vitest + Testing Libraryでfallback表示、onError、retry resetのテストを追加すること。
- 変更後にnpm run typecheck、npx vitest run、npm run buildを実行し、結果を報告すること。

既存のルーティング、ログ基盤、CSS規約を先に読んでから、最小差分で実装してください。

レビュー用の追加プロンプトも有効です。

今の差分をError Boundaryの観点でレビューしてください。
特に、過剰な境界、捕捉できない非同期エラーの放置、PII漏えい、resetKeys不足、fallback UIのアクセシビリティ、テスト不足を指摘してください。
コード変更はせず、ファイル名と行番号つきで問題だけを列挙してください。

3つ以上の実用ユースケース

1つ目はSaaSダッシュボードです。売上グラフ、アクティブユーザー表、通知パネルをそれぞれ部品単位で囲むと、グラフライブラリの例外で設定画面や請求導線まで止まる事故を避けられます。ログのfeatureにはdashboard.revenue-chartのような名前を入れると調査が速くなります。

2つ目は記事編集画面です。Markdownプレビュー、画像アップロードプレビュー、AI要約パネルは壊れやすい一方、本文入力フォームは守りたい領域です。プレビューだけ境界で囲み、保存ボタンの失敗はイベントハンドラで通常のエラーとして表示します。

3つ目はECや申込フォームです。決済処理の失敗をError Boundaryに任せるのは危険です。カード拒否、3Dセキュア失敗、在庫切れはユーザーに具体的な回復手順を出します。一方で、おすすめ商品枠やキャンペーンバナーのレンダー例外は部品単位の境界で隔離できます。

4つ目は管理者向けの監査ログ画面です。巨大なJSONを整形表示するビューアは例外を投げやすいので、ビューアだけ境界で囲みます。画面全体を落とさなければ、管理者は検索条件を変える、CSVを出す、別ユーザーを確認する、といった作業を続けられます。

落とし穴と公開前チェック

よくある落とし穴は、try/catchでJSX全体を囲んで安心してしまうことです。Reactのレンダー例外はその形では期待通りに捕まりません。次に、すべてのエラーを境界へ投げることです。入力ミスや認証切れのような回復可能な状態は、通常のUIで扱うべきです。

ログにも注意が必要です。window.location.hrefを送ると検索クエリやメールアドレスが混ざることがあります。error.messageにAPIレスポンス全文を詰めた例外を投げるコードもあります。境界実装だけでなく、例外を作る側のコードもレビュー対象にしてください。

公開前のチェックリストは次の通りです。

  • ルート単位と部品単位の境界が意図した粒度になっている
  • フォールバックUIにrole="alert"、見出し、再試行ボタンがある
  • 再試行で同じ例外に戻る場合の説明や再読み込み導線がある
  • PII、Cookie、Authorization、クエリ文字列をログ送信していない
  • componentDidCatchのログ関数が失敗しても画面をさらに壊さない
  • Vitestでfallback、onError、resetを確認している
  • npm run typecheck、対象テスト、npm run buildが通っている

チーム導入では、この記事のプロンプトを.claude/commands/review-error-boundary.mdのようなカスタムコマンドにすると再利用しやすくなります。Claude Codeの導入ルール作りやレビュー訓練までまとめて整えたい場合は、Claude Code研修・導入相談への導線を用意しておくと、記事から自然に実務支援へつなげられます。

まとめ

Error Boundaryは「何でも捕まえる魔法」ではなく、Reactのレンダー失敗をユーザー体験と運用ログに変換するための境界です。Claude Codeに任せるなら、捕捉できる範囲、ルート単位と部品単位の配置、リセット条件、PIIを含まないログ、テスト、検証コマンドまで一緒に指定してください。

この記事で紹介した内容を実際に試した結果、単にError Boundaryを置くよりも、resetKeysとログマスクを先に決めたほうがレビュー時間を短縮できました。特にダッシュボードのような複数ウィジェット画面では、壊れた部分だけを止める設計にすると、ユーザーの作業継続と開発者の原因調査を両立しやすくなります。

#Claude Code #React #Error Boundary #エラーハンドリング #TypeScript
無料

無料PDF: Claude Code はじめてのチートシート

まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。

スパムは送りません。登録情報は厳重に管理します。

Claude Codeを仕事で使える形にしませんか?

無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。

Masa

この記事を書いた人

Masa

Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。

PR

関連書籍・参考図書

この記事のテーマに関連する書籍を楽天ブックスで探せます。

※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。