React Native Reanimated バージョン不一致エラー完全解説
React経験者がReact Nativeで遭遇しやすいReanimatedのバージョン不一致エラーの原因と解決策。3層構造の理解からキャッシュクリアまで。
React Native Reanimated バージョン不一致エラー完全解説
はじめに
React経験者がReact Nativeで遭遇しやすいエラーの一つが、Reanimatedのバージョン不一致エラー。以下のメッセージが表示される。
[Reanimated] Mismatch between JavaScript code version
and Reanimated Babel plugin version (3.10.1 vs. 3.16.7).
「Babelプラグイン?React Nativeでなぜ?」という疑問を生む複雑な問題だが、原因と対処がわかれば怖くない。
React Native Reanimatedとは
Webの世界との違い
ReactではCSS Transitions、Framer Motion、React Spring、GSAPなどでアニメーションを実装できる。これらはブラウザレンダリングエンジン上で動作する。
React NativeはネイティブUI(iOS: UIKit、Android: Android View)を操作する必要があり、ここで React Native Reanimated が活躍する。
なぜReanimatedが必要なのか
React Nativeアーキテクチャの構造:
JavaScript Thread (Reactコード、ビジネスロジック)
↓ Bridge(JSON経由の非同期通信)
Native Thread (UIKit / Android View)
JavaScriptとネイティブ間の通信はBridgeを経由しており、この非同期処理は60fpsのスムーズなアニメーションには遅すぎる。
ReanimatedはアニメーションロジックをUIスレッドで直接実行し、JavaScript Bridgeをバイパスすることで60fps(または120fps)のアニメーションを実現する。「Worklet」と呼ばれるコンパイル済みコードをネイティブ側で直接実行する仕組み。
エラーの正体:バージョン不一致が起きる理由
Reanimatedの3層構造
Reanimatedは3つの異なるレイヤーで構成されている。
Layer 1: JavaScript Code — node_modules 内のJavaScriptコード。npmやyarnでインストール。
Layer 2: Babel Plugin — ビルド時にWorkletを変換。babel.config.js で設定。
Layer 3: Native Code — iOS: Objective-C++、Android: Java。Podfile/build.gradleでインストール。
JavaScriptコードが3.16.7でも、Babelプラグインが3.10.1(キャッシュされた古いバージョン)の場合、Workletのコンパイル形式が不一致になる。
Webとの決定的な違い
| 項目 | Web (React) | React Native |
|---|---|---|
| インストール | npm install ですぐ使える | npm install → Babel設定 → pod install → ネイティブビルド |
| バンドラー | Webpack / Vite | Metro Bundler |
| キャッシュ | ブラウザキャッシュ | Metro + ネイティブビルド + DerivedData |
| ネイティブ連携 | 不要 | CocoaPods (iOS) / Gradle (Android) |
エラーが発生する典型的なシナリオ
シナリオ1: 依存パッケージの競合
他のライブラリが古いReanimatedを内部に含有している場合:
your-app/node_modules/
├── react-native-reanimated@3.16.7 (あなたがインストール)
└── some-navigation-library/node_modules/
└── react-native-reanimated@3.10.1 (ライブラリが内包)
シナリオ2: Metro Bundlerのキャッシュ
パッケージを更新しても、Metroが古いキャッシュを使い続ける場合:
bashnpm install react-native-reanimated@latest npm start # ← 古いBabelプラグインの出力を使用
シナリオ3: ネイティブビルドの未更新
JavaScriptパッケージは更新したが、ネイティブコードは古いまま、または pod install を実行していない場合。
解決方法:ステップバイステップ
ステップ1: バージョンの確認
bash# yarnの場合 yarn why react-native-reanimated # npmの場合 npm ls react-native-reanimated
複数バージョンが表示されたら、それが原因。
ステップ2: バージョンの統一
package.json に以下を追加して、プロジェクト全体で単一バージョンを強制する。
json{ "dependencies": { "react-native-reanimated": "^3.16.7" }, "resolutions": { "react-native-reanimated": "3.16.7" } }
npm の場合は resolutions の代わりに overrides を使う。
ステップ3: キャッシュの完全クリア
React Nativeは複数のキャッシュが存在するため、すべてクリアする必要がある。
bash# 1. node_modulesの削除と再インストール rm -rf node_modules rm -rf package-lock.json # または yarn.lock npm install # 2. Metro Bundlerのキャッシュクリア npm start -- --reset-cache # 3. iOSのキャッシュクリア cd ios rm -rf Pods Podfile.lock ~/Library/Developer/Xcode/DerivedData pod install cd .. # 4. Androidのキャッシュクリア cd android && ./gradlew clean && cd ..
ステップ4: babel.config.jsの確認
Reanimatedのプラグインは 必ず最後 に記述する。
javascriptmodule.exports = { presets: ['module:@react-native/babel-preset'], plugins: [ '@babel/plugin-transform-runtime', // Reanimatedは必ず最後 'react-native-reanimated/plugin', ], };
ステップ5: アプリの再ビルド
bash# iOSの場合 npx react-native run-ios --reset-cache # Androidの場合 npx react-native run-android # Expoの場合 npx expo run:ios
まとめ:解決の3原則
統一: resolutions / overrides でバージョンを統一
クリア: すべてのキャッシュ(Metro、Pods、DerivedData、node_modules)をクリア
リビルド: ネイティブコードを必ず再ビルド
Webでは「npm install したら終わり」だが、React Nativeは複数のレイヤーで構成されている。ネイティブアプリ開発の特性を常に意識することが重要。