◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Expo SDK 58 が 10/15 に正式リリースされました(Beta は 09/15 から)。上げる前に依存の対応状況を確認しましょう●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Expo SDK 58 が 10/15 に正式リリースされました(Beta は 09/15 から)。上げる前に依存の対応状況を確認しましょう●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-03-28上級

Rork Max エラーハンドリング・デバッグ・本番監視の実践パターン — 堅牢なアプリを構築する上級テクニック

Rork Max のアプリに本番品質の堅牢性を持たせるための実践パターン。Error Boundary の多層配置、グローバルエラー捕捉、構造化ロガー、Sentry/Crashlytics 統合に加え、複数アプリの運用で得た差分監視やログサンプリングの工夫を共有します。

Rork Max236エラーハンドリング5デバッグ22本番監視Sentry6React Native240Error Boundaryログ設計

✦ プレミアム記事

アプリを1本でも本番リリースすると、「ローカルでは再現しないのに、特定のユーザーだけがクラッシュする」という壁に必ずぶつかります。2014年から個人でアプリを運営してきた経験から、この壁を越えるための実装パターンを順にお伝えします。

取り組みの背景 — なぜエラーハンドリングと監視が重要なのか

アプリ開発において、機能の実装だけでは不十分です。本番環境にリリースしたアプリがクラッシュすれば、ユーザーの信頼を失い、App Store のレビュー評価も下がります。Rork Max を使えばアプリの構築は驚くほど速くなりますが、堅牢性を確保するためのエラーハンドリングと監視体制は開発者自身が設計する必要があります。

Rork Max で構築するアプリに適用できるエラーハンドリング・デバッグ・本番監視の実践パターンを、実際の運用で効いた工夫とあわせて取り上げます。React Native(Expo)のエコシステムを前提に、初期開発からリリース後の運用まで、一貫したエラー対策を構築する方法を学べます。

対象読者: Rork でアプリを1本以上リリースした経験がある方、または本番運用を見据えた設計に取り組みたい中上級者の方

前提知識: React Native / Expo の基礎、TypeScript の基本構文、Rork Max の基本操作

Error Boundary による UI レベルのエラー防御

React のコンポーネントツリーで発生するレンダリングエラーは、アプリ全体をクラッシュさせる原因になります。Error Boundary を正しく配置することで、障害の影響範囲を最小限に抑えられます。

基本的な Error Boundary の実装

// components/ErrorBoundary.tsx
import React, { Component, ReactNode } from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
 
interface Props {
  children: ReactNode;
  fallback?: ReactNode;
  onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
}
 
interface State {
  hasError: boolean;
  error: Error | null;
}
 
class ErrorBoundary extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { hasError: false, error: null };
  }
 
  static getDerivedStateFromError(error: Error): State {
    return { hasError: true, error };
  }
 
  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
    // エラーログをリモートに送信
    this.props.onError?.(error, errorInfo);
    console.error('[ErrorBoundary]', error.message, errorInfo.componentStack);
  }
 
  handleRetry = () => {
    this.setState({ hasError: false, error: null });
  };
 
  render() {
    if (this.state.hasError) {
      if (this.props.fallback) {
        return this.props.fallback;
      }
      return (
        <View style={styles.container}>
          <Text style={styles.title}>問題が発生しました</Text>
          <Text style={styles.message}>
            {this.state.error?.message || '予期しないエラーが発生しました'}
          </Text>
          <TouchableOpacity style={styles.button} onPress={this.handleRetry}>
            <Text style={styles.buttonText}>もう一度試す</Text>
          </TouchableOpacity>
        </View>
      );
    }
    return this.props.children;
  }
}
 
const styles = StyleSheet.create({
  container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 24 },
  title: { fontSize: 20, fontWeight: 'bold', marginBottom: 12 },
  message: { fontSize: 14, color: '#666', textAlign: 'center', marginBottom: 24 },
  button: { backgroundColor: '#007AFF', paddingHorizontal: 24, paddingVertical: 12, borderRadius: 8 },
  buttonText: { color: '#fff', fontSize: 16, fontWeight: '600' },
});
 
export default ErrorBoundary;

多層 Error Boundary 戦略

単一の Error Boundary ですべてをカバーするのではなく、アプリのレイヤーごとに配置するのが上級パターンです。

// app/_layout.tsx — ルートレベルの Error Boundary
import ErrorBoundary from '@/components/ErrorBoundary';
import { reportToSentry } from '@/utils/errorReporter';
 
export default function RootLayout() {
  return (
    <ErrorBoundary onError={reportToSentry} fallback={<CriticalErrorScreen />}>
      <NavigationContainer>
        <ErrorBoundary onError={reportToSentry}>
          {/* 画面レベルのエラーは個別にキャッチ */}
          <MainStack />
        </ErrorBoundary>
      </NavigationContainer>
    </ErrorBoundary>
  );
}

この設計では、ルートレベルの Error Boundary がナビゲーション自体の障害をキャッチし、画面レベルの Error Boundary が個別画面のレンダリングエラーを処理します。ユーザーは画面単位でリトライでき、アプリ全体のクラッシュを回避できます。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦リリース前後のクラッシュフリー率を絶対値ではなく差分で監視し、不具合検知を半日早めた実装
✦リモートログをエラー単位ではなくユーザー単位でサンプリングし送信量を約1/8に削減する設計
✦beforeSend で対処不能なエラーを切り分け、対応すべき通知を月70件から12件前後に減らす運用ノウハウ
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⬡ 開発ツール2026-09-10
画面を暗くする機能を足したら、アプリを閉じたあとも iPhone が暗いままでした
expo-brightness の setBrightnessAsync は、Android では現在のアクティビティにだけ効き、iOS では端末の明るさそのものを変えます。戻す責任が片側にしかない理由と、AppState で後始末をするフックの実装をまとめました。
⬡ 開発ツール2026-09-04
EAS の secret は「アプリに入れない」設定ではありません — 接頭辞と可視性を別々に決める
EXPO_PUBLIC_ の接頭辞は成果物に入るかを決め、EAS の可視性は誰が読めるかを決めます。二つを重ねたときに OTA 更新でだけ値が消える筋道と、出荷前に自分の手で確かめる手順をまとめました。
⬡ 開発ツール2026-09-01
expo-paste-input で画像を貼り付けられる入力欄を作り、消える file:// を documents へ逃がす
チャット入力に画像やGIFを貼り付けられるようにする expo-paste-input の実装手順です。onPaste が返す file:// は一時ファイルで、送信までの間に消えることがあります。保存先を移す実装と、実機で確かめる順番をまとめました。