mcpField
R
react-native-expo

react-native-expo

github.com/jezweb開発1.1k738 回インストール3 週間前に更新
リポジトリ

react-native-expo について

新しい React Native を使う開発者向けに、Expo SDK 52 以降の設定、アップグレード、API 変更、既知の問題を解説するスキルです。

主な機能

  1. 01Expo プロジェクトの設定と開発コマンド
  2. 02新アーキテクチャへの移行ガイド
  3. 03React 19 と React Native の API 変更
  4. 04React Native DevTools によるデバッグ
  5. 05既知の問題の予防と回避策

活用シーン

  1. 01新しい Expo モバイルアプリの開始
  2. 02プロジェクトの新しい SDK へのアップグレード
  3. 03ビルドやデバッグ問題の調査

インストール

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

$npx skills add https://github.com/jezweb/claude-skills --skill react-native-expo

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
.claude-plugin/
plugin.json
agents/
expo-build.md
assets/
css-features-cheatsheet.md
example-template.txt
new-arch-decision-tree.md
references/
example-reference.md
expo-sdk-52-breaking.md
new-architecture-errors.md
react-19-migration.md
scripts/
check-rn-version.sh
example-script.sh

詳細

React Native Expo(0.76-0.82+ / SDK 52+)

ステータス:本番環境対応 最終更新日:2026-01-21 依存関係:Node.js 20.19.4+、Expo CLI、Xcode 16.1+(iOS) 最新バージョン:[email protected]、expo@~54.0.31、[email protected]


クイックスタート(15 分)

1. Expo プロジェクトを新規作成する(RN 0.76+)
# Create new Expo app with React Native 0.76+
npx create-expo-app@latest my-app

cd my-app

# Install latest dependencies
npx expo install react-native@latest expo@latest

重要な理由:

  • Expo SDK 52+ は、デフォルトで新アーキテクチャが有効になった React Native 0.76+ を使用します
  • React Native 0.82+ では新アーキテクチャが必須です(無効にできません)
  • Hermes のみがサポート対象の JavaScript エンジンです(Expo Go から JSC は削除されました)
2. 新アーキテクチャが有効になっていることを確認する
# Check if New Architecture is enabled (should be true by default)
npx expo config --type introspect | grep newArchEnabled

重要:

  • React Native 0.82+ では新アーキテクチャが必須です。レガシーアーキテクチャは完全に削除されています
  • 0.75 以前から移行する場合は、まず 0.76-0.81 にアップグレードして、相互運用レイヤーを使用してください
  • 0.82+ で新アーキテクチャを無効にしようとしないでください(ビルドに失敗します)
3. 開発サーバーを起動する
# Start Expo dev server
npx expo start

# Press 'i' for iOS simulator
# Press 'a' for Android emulator
# Press 'j' to open React Native DevTools (NOT Chrome debugger!)

重要:

  • 古い Chrome デバッガーは 0.79 で削除されました。代わりに React Native DevTools を使用してください
  • Metro ターミナルには console.log() が出力されなくなりました。DevTools Console を使用してください
  • キーボードショートカット「a」/「i」は CLI では機能しますが、Metro ターミナルでは機能しません

重大な破壊的変更(2024 年 12 月以降)

🔴 新アーキテクチャが必須(0.82+)

SDK のスケジュール:

  • Expo SDK 54(React Native 0.81):レガシーアーキテクチャをサポートする最後のリリース
  • Expo SDK 55(React Native 0.83):新アーキテクチャが必須となり、レガシーアーキテクチャは完全に削除

変更点:

  • 0.76-0.81 / SDK 52-54:新アーキテクチャがデフォルト、レガシーアーキテクチャは凍結(新機能の追加なし)
  • 0.82+ / SDK 55+:レガシーアーキテクチャはコードベースから完全に削除

影響:

# This will FAIL in 0.82+ / SDK 55+:
# gradle.properties (Android)
newArchEnabled=false  # ❌ Ignored, build fails

# iOS
RCT_NEW_ARCH_ENABLED=0  # ❌ Ignored, build fails

移行手順:

  1. まず 0.76-0.81 / SDK 54 にアップグレードします(0.75 以前を使用している場合)
  2. 新アーキテクチャを有効にしてテストします
  3. 互換性のない依存関係(Redux、i18n、CodePush、Reanimated v3 → v4)を修正します
  4. その後、0.82+ / SDK 55+ にアップグレードします

出典: Expo SDK 54 Changelog

🔴 propTypes の削除(React 19 / RN 0.78+)

変更点: React 19 では propTypes が完全に削除されました。実行時の検証も警告もなく、何も通知されずに無視されます。

変更前(古いコード):

import PropTypes from 'prop-types';

function MyComponent({ name, age }) {
  return <Text>{name} is {age}</Text>;
}

MyComponent.propTypes = {  // ❌ Silently ignored in React 19
  name: PropTypes.string.isRequired,
  age: PropTypes.number
};

変更後(TypeScript を使用):

type MyComponentProps = {
  name: string;
  age?: number;
};

function MyComponent({ name, age }: MyComponentProps) {
  return <Text>{name} is {age}</Text>;
}

移行:

# Use React 19 codemod to remove propTypes
npx @codemod/react-19 upgrade
🔴 forwardRef の非推奨化(React 19)

変更点: forwardRef は不要になりました。通常の prop として ref を渡してください。

変更前(古いコード):

import { forwardRef } from 'react';

const MyInput = forwardRef((props, ref) => {  // ❌ Deprecated
  return <TextInput ref={ref} {...props} />;
});

変更後(React 19):

function MyInput({ ref, ...props }) {  // ✅ ref is a regular prop
  return <TextInput ref={ref} {...props} />;
}
🔴 Swift iOS テンプレートがデフォルトに(0.77+)

変更点: 新規プロジェクトでは、Objective-C の AppDelegate.mm ではなく Swift の AppDelegate.swift を使用します。

以前の構成:

ios/MyApp/
├── main.m              # ❌ Removed
├── AppDelegate.h       # ❌ Removed
└── AppDelegate.mm      # ❌ Removed

新しい構成:

// ios/MyApp/AppDelegate.swift ✅
import UIKit
import React

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
  func application(_ application: UIApplication, ...) -> Bool {
    // App initialization
    return true
  }
}

移行(0.76 → 0.77): 既存のプロジェクトをアップグレードする場合は、この行を必ず追加してください:

// Add to AppDelegate.swift during migration
import React
import ReactCoreModules

RCTAppDependencyProvider.sharedInstance()  // ⚠️ CRITICAL: Must add this!

出典: React Native 0.77 Release Notes

🔴 Metro のログ転送を削除(0.77+)

変更点: Metro ターミナルには console.log() の出力が表示されなくなりました。

変更前(0.76):

# console.log() appeared in Metro terminal
$ npx expo start
> LOG  Hello from app!  # ✅ Appeared here

変更後(0.77+):

# console.log() does NOT appear in Metro terminal
$ npx expo start
# (no logs shown)  # ❌ Removed

# Workaround (temporary, will be removed):
$ npx expo start --client-logs  # Shows logs, deprecated

解決方法: 代わりに React Native DevTools Console を使用してください(CLI で「j」を押します)。

出典: React Native 0.77 Release Notes

🔴 Chrome デバッガーの削除(0.79+)

変更点: 古い Chrome デバッガー(chrome://inspect)は削除されました。代わりに React Native DevTools を使用してください。

以前の方法(削除済み):

# ❌ This no longer works:
# Open Dev Menu → "Debug" → Chrome DevTools opens

新しい方法(0.76+):

# Press 'j' in CLI or Dev Menu → "Open React Native DevTools"
# ✅ Uses Chrome DevTools Protocol (CDP)
# ✅ Reliable breakpoints, watch values, stack inspection
# ✅ JS Console (replaces Metro logs)

制限事項:

  • サードパーティ製拡張機能はまだサポートされていません(Redux DevTools など)
  • ネットワークインスペクターは 0.83 で追加予定(2025 年後半)

出典: React Native 0.79 Release Notes

🔴 JSC エンジンがコミュニティに移行(0.79+)

変更点: JavaScriptCore(JSC)のファーストパーティサポートが React Native 0.81+ のコアから削除され、コミュニティパッケージに移行しました。

変更前(0.78):

  • Hermes と JSC の両方が React Native にバンドルされていました
  • JSC は Expo Go で利用できました

変更後(0.79+ / React Native 0.81+ / SDK 54):

# JSC removed from React Native core
# If you still need JSC (rare):
npm install @react-native-community/javascriptcore

Expo Go:

  • SDK 52+:JSC は Expo Go から完全に削除されました
  • Hermes のみがサポートされています

注: JSC は最終的に React Native から完全に削除される予定です。

出典: Expo SDK 54 Changelog

🔴 ディープインポートの非推奨化(0.80+)

変更点: 内部パスからのインポートは動作しなくなります。

変更前(古いコード):

// ❌ Deep imports deprecated
import Button from 'react-native/Libraries/Components/Button';
import Platform from 'react-native/Libraries/Utilities/Platform';

変更後:

// ✅ Import only from 'react-native'
import { Button, Platform } from 'react-native';

出典: React Native 0.80 Release Notes

🔴 Android のエッジツーエッジ表示が必須に(SDK 54+)

変更点: エッジツーエッジ表示は SDK 54 のすべての Android アプリでデフォルトで有効になり、無効にできません。

影響:

// app.json or app.config.js
{
  "expo": {
    "android": {
      // This setting is now IGNORED - edge-to-edge always enabled
      "edgeToEdgeEnabled": false  // ❌ No effect in SDK 54+
    }
  }
}

UI への影響: コンテンツはシステムステータスバーとナビゲーションバーの背後まで表示されるようになりました。react-native-safe-area-context を使用して、インセットを手動で考慮する必要があります。

解決策:

import { SafeAreaView } from 'react-native-safe-area-context';

function App() {
  return (
    <SafeAreaView style={{ flex: 1 }}>
      {/* Content respects system bars */}
    </SafeAreaView>
  );
}

出典: Expo SDK 54 Changelog


新機能(2024年12月以降)

CSS プロパティ(0.77+ の新アーキテクチャのみ)

React Native では、以前はウェブでしか利用できなかった多くの CSS プロパティがサポートされるようになりました。

1. display: contents

要素を「不可視」にしながら、その子要素をレイアウト内に保持します。

<View style={{ display: 'contents' }}>
  {/* This View disappears, but Text still renders */}
  <Text>I'm still here!</Text>
</View>

ユースケース: レイアウトに影響を与えるべきでないラッパーコンポーネント。

2. boxSizing

幅と高さの計算方法を制御します。

// Default: padding/border inside box
<View style={{
  boxSizing: 'border-box',  // Default
  width: 100,
  padding: 10,
  borderWidth: 2
  // Total width: 100 (padding/border inside)
}} />

// Content-box: padding/border outside
<View style={{
  boxSizing: 'content-box',
  width: 100,
  padding: 10,
  borderWidth: 2
  // Total width: 124 (100 + 20 padding + 4 border)
}} />
3. mixBlendMode + isolation

Photoshop のようにレイヤーをブレンドします。

<View style={{ backgroundColor: 'red' }}>
  <View style={{
    mixBlendMode: 'multiply',  // 16 modes available
    backgroundColor: 'blue'
    // Result: purple (red × blue)
  }} />
</View>

// Prevent unwanted blending:
<View style={{ isolation: 'isolate' }}>
  {/* Blending contained within this view */}
</View>

利用可能なモード: multiply、screen、overlay、darken、lighten、color-dodge、color-burn、hard-light、soft-light、difference、exclusion、hue、saturation、color、luminosity

4. outline プロパティ

レイアウトに影響しない(border とは異なる)視覚的なアウトラインです。

<View style={{
  outlineWidth: 2,
  outlineStyle: 'solid',      // solid | dashed | dotted
  outlineColor: 'blue',
  outlineOffset: 4,           // Space between element and outline
  outlineSpread: 2            // Expand outline beyond offset
}} />

主な違い: アウトラインは要素のサイズを変えず、レイアウトの再計算も発生させません。

出典: React Native 0.77 Release Notes

Android XML ドローアブル(0.78+)

ネイティブ Android のベクタードローアブル(XML)を Image のソースとして使用できます。

// Load XML drawable at build time
import MyIcon from './assets/my_icon.xml';

<Image
  source={MyIcon}
  style={{ width: 40, height: 40 }}
/>

// Or with require:
<Image
  source={require('./assets/my_icon.xml')}
  style={{ width: 40, height: 40 }}
/>

メリット:

  • 拡大縮小可能なベクター画像(解像度に依存しません)
  • PNG と比べて APK のサイズが小さくなります
  • オフスレッドでデコードされます(パフォーマンスが向上します)

制約:

  • ビルド時のリソースのみ(ネットワークからの読み込みには対応していません)
  • Android のみ(iOS では引き続き SF Symbols または PNG を使用します)

出典: React Native 0.78 Release Notes

React 19 の新しいフック
1. useActionState(フォームパターンに代わるもの)
import { useActionState } from 'react';

function MyForm() {
  const [state, submitAction, isPending] = useActionState(
    async (prevState, formData) => {
      // Async form submission
      const result = await api.submit(formData);
      return result;
    },
    { message: '' }  // Initial state
  );

  return (
    <form action={submitAction}>
      <TextInput name="email" />
      <Button disabled={isPending}>
        {isPending ? 'Submitting...' : 'Submit'}
      </Button>
      {state.message && <Text>{state.message}</Text>}
    </form>
  );
}
2. useOptimistic(楽観的 UI 更新)
import { useOptimistic } from 'react';

function LikeButton({ postId, initialLikes }) {
  const [optimisticLikes, addOptimisticLike] = useOptimistic(
    initialLikes,
    (currentLikes, amount) => currentLikes + amount
  );

  async function handleLike() {
    addOptimisticLike(1);  // Update UI immediately
    await api.like(postId);  // Then update server
  }

  return (
    <Button onPress={handleLike}>
      ❤️ {optimisticLikes}
    </Button>
  );
}
3. use(レンダー中にプロミスやコンテキストを読み取ります)
import { use } from 'react';

function UserProfile({ userPromise }) {
  // Read promise directly during render (suspends if pending)
  const user = use(userPromise);

  return <Text>{user.name}</Text>;
}

出典: React 19 Upgrade Guide

React Native DevTools(0.76+)

アクセス方法:

  • CLI で j を押します
  • または Dev Menu → 「Open React Native DevTools」を開きます

機能:

  • ✅ 信頼性の高いブレークポイント(従来の Chrome デバッガーとは異なります)
  • ✅ 値の監視、コールスタックの検査
  • ✅ JS コンソール(Metro のログに代わるもの)
  • ✅ Chrome DevTools Protocol(CDP)ベース
  • ⏳ ネットワークインスペクター(0.83 で提供予定)
  • ❌ サードパーティの拡張機能はまだサポートされていません

出典: React Native DevTools Announcement


既知の問題の予防

このスキルは、ドキュメント化された 16 件の問題を防ぎます。

Issue #1: propTypes が警告なく無視される

エラー: エラーは発生せず、propTypes が機能しません 出典: React 19 Upgrade Guide 発生する理由: React 19 では実行時の propTypes 検証が削除されました 予防策: 代わりに TypeScript を使用し、npx @codemod/react-19 upgrade を実行して削除します

Issue #2:forwardRef の非推奨警告

エラー: Warning: forwardRef is deprecated 出典: React 19 Upgrade Guide 発生理由: React 19 では、通常のプロパティとして ref を使用できます 予防策: forwardRef のラッパーを削除し、プロパティとして ref を直接渡します

Issue #3:新しいアーキテクチャを無効化できない(0.82 以降)

エラー: newArchEnabled=false でビルドが失敗します 出典: React Native 0.82 Release Notes 発生理由: レガシーアーキテクチャがコードベースから完全に削除されました 予防策: 0.82 以降にアップグレードする前に、新しいアーキテクチャへ移行します

Issue #4:「Fabric component descriptor not found」

エラー: Fabric component descriptor provider not found for component 出典: New Architecture Migration Guide 発生理由: コンポーネントが新しいアーキテクチャ(Fabric)に対応していません 予防策: ライブラリを新しいアーキテクチャ対応バージョンに更新するか、相互運用レイヤーを使用します(0.76~0.81)

Issue #5:「TurboModule not registered」

エラー: TurboModule '[ModuleName]' not found 出典: New Architecture Migration Guide 発生理由: ネイティブモジュールには、新しいアーキテクチャ(TurboModules)のサポートが必要です 予防策: ライブラリを TurboModules 対応に更新するか、相互運用レイヤーを使用します(0.76~0.81)

Issue #6:Swift の AppDelegate に RCTAppDependencyProvider がない

エラー: RCTAppDependencyProvider not found 出典: React Native 0.77 Release Notes 発生理由: Objective-C のテンプレートから Swift のテンプレートに移行する場合に発生します 予防策: AppDelegate.swift に RCTAppDependencyProvider.sharedInstance() を追加します

Issue #7:Metro のログが表示されない

エラー: console.log() がターミナルに表示されません 出典: React Native 0.77 Release Notes 発生理由: Metro のログ転送は 0.77 で削除されました 予防策: React Native DevTools のコンソール(「j」を押す)を使用するか、一時的に --client-logs フラグを使用します

Issue #8:Chrome デバッガーが動作しない

エラー: Chrome DevTools が接続されません 出典: React Native 0.79 Release Notes 発生理由: 従来の Chrome デバッガーは 0.79 で削除されました 予防策: 代わりに React Native DevTools を使用します(「j」を押す)

Issue #9:深いパスからのインポートエラー

エラー: Module not found: react-native/Libraries/... 出典: React Native 0.80 Release Notes 発生理由: 内部パスが非推奨となり、厳格な API が適用されました 予防策: 深いパスではなく、'react-native' からのみインポートします

Issue #10:新しいアーキテクチャで Redux ストアがクラッシュする

エラー: Redux ストアの作成時にアプリがクラッシュします 出典: Redux Toolkit Migration Guide 発生理由: 古い redux と redux-thunk は新しいアーキテクチャと互換性がありません 予防策: 代わりに Redux Toolkit(@reduxjs/toolkit)を使用します

Issue #11:新しいアーキテクチャで i18n-js が不安定

エラー: 翻訳が更新されない、またはアプリがクラッシュします 出典: コミュニティからの報告(GitHub の Issue) 発生理由: i18n-js は新しいアーキテクチャと完全には互換性がありません 予防策: 代わりに react-i18next を使用します

Issue #12:Android で CodePush がクラッシュする

エラー: Android が null という名前のバンドルを探してクラッシュします 出典: CodePush GitHub Issues 発生理由: 新しいアーキテクチャとの既知の非互換性があります 予防策: 新しいアーキテクチャでは CodePush の使用を避けるか、公式サポートを待ちます

Issue #13: expo-file-system のレガシー API が削除されました (SDK 55+)

エラー: Module not found: expo-file-system/legacy 出典: Expo SDK 54 Changelog、GitHub Issue #39056 発生する理由: レガシー API は SDK 55 で削除されたため、新しい File/Directory クラス API へ移行する必要があります 防止策: SDK 55 にアップグレードする前に新しい API へ移行してください

移行のタイムライン:

  • SDK 53 以前: レガシー API は expo-file-system に配置
  • SDK 54: レガシー API は expo-file-system/legacy、新しい API は expo-file-system (デフォルト)
  • SDK 55: レガシー API は完全に削除

旧コード (SDK 54 でレガシーインポートを使用):

import * as FileSystem from 'expo-file-system/legacy';
await FileSystem.writeAsStringAsync(uri, content);

新コード (SDK 54+ の新しい API):

import { File } from 'expo-file-system';
const file = new File(uri);
await file.writeString(content);
Issue #14: expo-av が削除されました (SDK 55+)

エラー: Module not found: expo-av 出典: Expo SDK 54 Changelog、expo-av GitHub 発生する理由: このパッケージは SDK 53 で非推奨となり、SDK 55 で削除されました 防止策: SDK 55 より前に expo-audio と expo-video へ移行してください

移行のタイムライン:

  • SDK 52: expo-video が導入
  • SDK 53: expo-audio が導入され、expo-av が非推奨に
  • SDK 54: expo-av を含む最後のリリース (パッチなし)
  • SDK 55: expo-av が削除

移行 - オーディオ:

// OLD: expo-av
import { Audio } from 'expo-av';
const { sound } = await Audio.Sound.createAsync(require('./audio.mp3'));
await sound.playAsync();

// NEW: expo-audio
import { useAudioPlayer } from 'expo-audio';
const player = useAudioPlayer(require('./audio.mp3'));
player.play();

移行 - ビデオ:

// OLD: expo-av
import { Video } from 'expo-av';
<Video source={require('./video.mp4')} />

// NEW: expo-video
import { VideoView } from 'expo-video';
<VideoView source={require('./video.mp4')} />
Issue #15: Reanimated v4 は新しいアーキテクチャが必要です

エラー: レガシーアーキテクチャで Reanimated v4 を使用するとビルドが失敗するかクラッシュします 出典: Expo SDK 54 FYI 発生する理由: Reanimated v4 は新しいアーキテクチャのみを必要とします 防止策: レガシーアーキテクチャでは Reanimated v3 を使用するか、先に新しいアーキテクチャへ移行してください

バージョン対応表:

Reanimated バージョンアーキテクチャのサポートExpo SDK
v3レガシー + 新しいアーキテクチャSDK 52-54
v4新しいアーキテクチャのみSDK 54+

NativeWind の非互換性:

# NativeWind does not support Reanimated v4 yet (as of Jan 2026)
# If using NativeWind, must stay on Reanimated v3
npm install react-native-reanimated@^3

v4 への移行 (新しいアーキテクチャのみ):

  1. react-native-worklets をインストールする (v4 で必須)
  2. 公式の Reanimated v3 → v4 移行ガイドに従う
  3. babel-preset-expo を使用している場合は babel.config.js の変更をスキップする (自動設定されます)
Issue #16: Hermes + 新しいアーキテクチャで iOS が起動時にクラッシュする (SDK 54) - コミュニティ提供

エラー:

hermes::vm::JSObject::putComputed_RJS
hermes::vm::arrayPrototypePush

出典: GitHub Issue #41824、Medium Post 検証済み: 再現可能 発生する理由: iOS で新しいアーキテクチャを使用する場合、Expo Updates は Podfile に明示的な :hermes_enabled フラグを必要とします 防止策: ios/Podfile に明示的な Hermes フラグを追加してください

条件:

  • Expo SDK 54
  • 新しいアーキテクチャが有効
  • Hermes が有効 (デフォルト)
  • expo-updates を使用している
  • iOS のみ (Android は影響を受けません)

回避策:

# ios/Podfile
use_frameworks! :linkage => :static
ENV['HERMES_ENABLED'] = '1'  # ⚠️ CRITICAL: Must be explicit with New Arch + expo-updates

注記: これは再現リポジトリを伴うコミュニティ提供の知見であり、まだ Expo の変更履歴に公式には文書化されていません。


移行ガイド: 0.72-0.75 → 0.82+

ステップ 1: まず相互運用レイヤーへアップグレードする (0.76-0.81)

理由: レガシーアーキテクチャを使用している場合、0.82 へ直接スキップすることはできません。相互運用レイヤーを失うことになります。

# Check current version
npx react-native --version

# Upgrade to 0.81 first (last version with interop layer)
npm install [email protected]
npx expo install --fix
ステップ 2: 新しいアーキテクチャを有効にする (まだの場合)
# Android (gradle.properties)
newArchEnabled=true

# iOS
RCT_NEW_ARCH_ENABLED=1 bundle exec pod install

# Rebuild
npm run ios
npm run android
ステップ 3: 互換性のない依存関係を修正する

よくある非互換性:

# Replace Redux with Redux Toolkit
npm uninstall redux redux-thunk
npm install @reduxjs/toolkit react-redux

# Replace i18n-js with react-i18next
npm uninstall i18n-js
npm install react-i18next i18next

# Update React Navigation (if old version)
npm install @react-navigation/native@latest
ステップ 4: 徹底的にテストする
# Run on both platforms
npm run ios
npm run android

# Test all features:
# - Navigation
# - State management (Redux)
# - API calls
# - Deep linking
# - Push notifications
ステップ 5: React 19 へ移行する (0.78+ へアップグレードする場合)
# Run React 19 codemod
npx @codemod/react-19 upgrade

# Manually verify:
# - Remove all propTypes declarations
# - Remove forwardRef wrappers
# - Update to new hooks (useActionState, useOptimistic)
ステップ 6: 0.82+ へアップグレードする
# Only after testing with New Architecture enabled!
npm install [email protected]
npx expo install --fix

# Rebuild
npm run ios
npm run android
ステップ 7: iOS を Swift へ移行する (新規プロジェクトの場合)

新規プロジェクト (0.77+) はデフォルトで Swift を使用します。既存のプロジェクトの場合:

# Follow upgrade helper
# https://react-native-community.github.io/upgrade-helper/
# Select: 0.76 → 0.77

# CRITICAL: Add this line to AppDelegate.swift
RCTAppDependencyProvider.sharedInstance()

一般的なパターン

パターン 1: 新しいフックによる条件付きレンダリング
import { useActionState } from 'react';

function LoginForm() {
  const [state, loginAction, isPending] = useActionState(
    async (prevState, formData) => {
      try {
        const user = await api.login(formData);
        return { success: true, user };
      } catch (error) {
        return { success: false, error: error.message };
      }
    },
    { success: false }
  );

  return (
    <View>
      <form action={loginAction}>
        <TextInput name="email" placeholder="Email" />
        <TextInput name="password" secureTextEntry />
        <Button disabled={isPending}>
          {isPending ? 'Logging in...' : 'Login'}
        </Button>
      </form>
      {!state.success && state.error && (
        <Text style={{ color: 'red' }}>{state.error}</Text>
      )}
    </View>
  );
}

使用する場面: ローディング状態やエラー状態を伴うフォーム送信

パターン 2:propTypes の代わりに TypeScript
// Define prop types with TypeScript
type ButtonProps = {
  title: string;
  onPress: () => void;
  disabled?: boolean;
  variant?: 'primary' | 'secondary';
};

function Button({ title, onPress, disabled = false, variant = 'primary' }: ButtonProps) {
  return (
    <Pressable
      onPress={onPress}
      disabled={disabled}
      style={[styles.button, styles[variant]]}
    >
      <Text style={styles.text}>{title}</Text>
    </Pressable>
  );
}

使用するタイミング: 常に(React 19 では propTypes が削除されています)

パターン 3:視覚効果には新しい CSS を使用
// Glowing button with outline and blend mode
function GlowButton({ title, onPress }) {
  return (
    <Pressable
      onPress={onPress}
      style={{
        backgroundColor: '#3b82f6',
        padding: 16,
        borderRadius: 8,
        // Outline doesn't affect layout
        outlineWidth: 2,
        outlineColor: '#60a5fa',
        outlineOffset: 4,
        // Blend with background
        mixBlendMode: 'screen',
        isolation: 'isolate'
      }}
    >
      <Text style={{ color: 'white', fontWeight: 'bold' }}>
        {title}
      </Text>
    </Pressable>
  );
}

使用するタイミング: レイアウトに影響しない視覚効果(New Architecture のみ)


バンドルされたリソースの使用

スクリプト(scripts/)

check-rn-version.sh - React Native のバージョンを検出し、アーキテクチャ要件について警告します

使用例:

./scripts/check-rn-version.sh
# Output: ✅ React Native 0.82 - New Architecture mandatory
# Output: ⚠️ React Native 0.75 - Upgrade to 0.76+ recommended
リファレンス(references/)

react-19-migration.md - React 19 の破壊的変更と移行手順の詳細

new-architecture-errors.md - New Architecture を有効にしたときによく発生するビルドエラー

expo-sdk-52-breaking.md - Expo SDK 52 以降固有の破壊的変更

Claude がこれらを読み込むタイミング: 移行エラーやビルドの失敗が発生した場合、または React 19 について詳しい質問があった場合

アセット(assets/)

new-arch-decision-tree.md - React Native のバージョンを選ぶための判断ツリー

css-features-cheatsheet.md - 新しい CSS プロパティの完全な使用例


Expo SDK 52 以降固有の情報

破壊的変更

Expo Go から JSC を削除:

// This no longer works in Expo Go (SDK 52+):
{
  "jsEngine": "jsc"  // ❌ Ignored, Hermes only
}

Expo Go から Google Maps を削除(SDK 53 以降):

# Must use custom dev client for Google Maps
npx expo install expo-dev-client
npx expo run:android

プッシュ通知に関する警告: Expo Go ではプッシュ通知に関する警告が表示されます。本番環境でのテストには、カスタム開発クライアントを使用してください。

新機能(SDK 52)

expo/fetch(WinterCG 準拠):

import { fetch } from 'expo/fetch';

// Standards-compliant fetch for Workers/Edge runtimes
const response = await fetch('https://api.example.com/data');

React Navigation v7:

npm install @react-navigation/native@^7.0.0

公式ドキュメント


パッケージバージョン(2026-01-21 確認済み)

ビルドツールの要件(SDK 54 以降):

  • Xcode: 最低 16.1、Xcode 16 を推奨
  • Node.js: 最低 20.19.4
  • iOS デプロイメントターゲット: iOS 15.1 以降

出典: Expo SDK 54 Changelog

{
  "dependencies": {
    "react": "^19.2.3",
    "react-native": "^0.81.5",
    "expo": "~54.0.31",
    "@react-navigation/native": "^7.0.0",
    "@reduxjs/toolkit": "^2.0.0",
    "react-i18next": "^15.0.0"
  },
  "devDependencies": {
    "@types/react": "^19.0.0",
    "typescript": "^5.7.0"
  }
}

トラブルシューティング

問題:「Fabric component descriptor not found」でビルドが失敗する

解決方法: ライブラリが New Architecture に対応していません。ライブラリのドキュメントで New Architecture のサポート状況を確認するか、相互運用レイヤーを使用してください(0.76~0.81 のみ)。

問題:「propTypes is not a function」エラーが発生する

解決方法: React 19 では propTypes が削除されています。代わりに TypeScript を使って型チェックを行ってください。npx @codemod/react-19 upgrade を実行してください。

問題:Metro ターミナルに console.log() が表示されない

解決方法: Metro のログ転送は 0.77 で削除されました。React Native DevTools Console(「j」を押す)または npx expo start --client-logs(一時的な回避策)を使用してください。

問題:iOS のビルド中に Swift の AppDelegate エラーが発生する

解決方法: AppDelegate.swift に RCTAppDependencyProvider.sharedInstance() を追加してください。Swift の移行に関するセクションを参照してください。

問題:起動時に Redux ストアがクラッシュする

解決方法: 従来の redux と redux-thunk の代わりに Redux Toolkit を使用してください。@reduxjs/toolkit をインストールしてください。

問題:0.82 以降で New Architecture を無効にできない

解決方法: 0.82 以降では New Architecture が必須です。従来のアーキテクチャが必要な場合は、0.81 以前を使用してください(推奨されません)。


セットアップ完全チェックリスト

このチェックリストを使って、セットアップを確認してください。

  • React Native 0.76+ または Expo SDK 52+ がインストールされている
  • 新アーキテクチャが有効になっている(0.82+ では自動)
  • Hermes エンジンが有効になっている(デフォルト)
  • React 19 への移行が完了している(propTypes、forwardRef は使用しない)
  • 型チェック用に TypeScript が設定されている
  • React Native DevTools にアクセスできる('j' キーを押す)
  • ディープインポートを使用していない(react-native/Libraries/*)
  • Redux Toolkit を使用している(レガシーな redux ではない)
  • react-i18next を使用している(i18n-js ではない)
  • iOS のビルドが成功する(新規プロジェクトでは Swift テンプレートを使用)
  • Android のビルドが成功する
  • 開発サーバーがエラーなく起動する
  • すべてのナビゲーション/状態管理が動作する

質問や問題がありますか?

  1. ビルドエラーについては references/new-architecture-errors.md を確認してください
  2. React 19 の問題については references/react-19-migration.md を確認してください
  3. 公式ドキュメントを確認してください:https://reactnative.dev/docs/new-architecture-intro
  4. 新アーキテクチャが有効になっていることを確認してください(0.82+ では必須)
  5. すべての依存関係が新アーキテクチャに対応していることを確認してください

解消される知識のギャップ: このスキルでは、2024 年 12 月以降の React Native の更新を扱います。LLM はこれらの更新を把握していません。このスキルがないと、Claude は非推奨の API、削除された機能、古いパターンを提案してしまいます。

コメント