「Reactは書けるけど、React Nativeは初めて」という方が最初にハマりやすいエラーの一つが、このReanimatedバージョン不一致エラーです。
[Reanimated] Mismatch between JavaScript code version and Reanimated Babel plugin version (3.10.1 vs. 3.16.7). See `https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooting` for more details.
このエラーを見て「Babelプラグイン?React Nativeでなぜ?」と思った方も多いはず。この記事では、React経験者の視点から、このエラーの原因と解決策を詳しく解説します。
Reactでアニメーションを実装する場合、以下のような選択肢があります:
これらはすべてブラウザのレンダリングエンジン上で動作します。
一方、React NativeではネイティブUI(iOS: UIKit、Android: Android View)を操作する必要があります。ここで登場するのが React Native Reanimated です。
React Nativeのアーキテクチャを図解すると:
┌─────────────────────────────────────────────────────────┐
│ JavaScript Thread │
│ (あなたのReactコード、ビジネスロジック、状態管理) │
└────────────────────────┬────────────────────────────────┘
│ Bridge(JSON経由の通信)
▼
┌─────────────────────────────────────────────────────────┐
│ Native Thread │
│ (UIKit / Android View - 実際のUI描画) │
└─────────────────────────────────────────────────────────┘
通常、JavaScriptとネイティブ間の通信はBridgeを経由します。この通信は非同期で、60fpsのスムーズなアニメーションには遅すぎることがあります。
┌─────────────────────────────────────────────────────────┐
│ JavaScript Thread │
│ Reanimated: アニメーション定義を「Worklet」として転送 │
└────────────────────────┬────────────────────────────────┘
│ Worklet(コンパイル済みコード)
▼
┌─────────────────────────────────────────────────────────┐
│ UI Thread │
│ Workletがネイティブ側で直接実行(Bridgeバイパス) │
└─────────────────────────────────────────────────────────┘
ここがReact経験者には分かりにくいポイントです。Reanimatedは3つの異なるレイヤーで構成されています:
┌─────────────────────────────────────────────────────────┐
│ Layer 1: JavaScript Code (node_modules内のJS) │
│ → npm/yarnでインストールされるJavaScriptコード │
│ → バージョン: 3.16.7 (例) │
└─────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────┐
│ Layer 2: Babel Plugin (ビルド時にWorkletを変換) │
│ → babel.config.jsで設定 │
│ → バージョン: 3.10.1 (例) ← ここが古い! │
└─────────────────────────────────────────────────────────┘
│
┌─────────────────────────────────────────────────────────┐
│ Layer 3: Native Code (iOS: Objective-C++, Android: Java)│
│ → Podfile/build.gradleでインストール │
│ → ネイティブビルド時にコンパイル │
└─────────────────────────────────────────────────────────┘
この不一致により、Workletのコンパイル形式が合わず、ランタイムエラーが発生します。
| 項目 | Web (React) | React Native |
|---|---|---|
| インストール | npm install → すぐ使える | npm install → Babel設定 → pod install → ネイティブビルド |
| バンドラー | Webpack / Vite | Metro Bundler |
| キャッシュ | ブラウザキャッシュ | Metro + ネイティブビルド + DerivedData |
| ネイティブ連携 | 不要 | CocoaPods (iOS) / Gradle (Android) |
your-app/
├── node_modules/
│ ├── react-native-reanimated@3.16.7 ← あなたがインストール
│ └── some-navigation-library/
│ └── node_modules/
│ └── react-native-reanimated@3.10.1 ← ライブラリが内包
原因: 他のライブラリが古いReanimatedを内部に持っている
# パッケージを更新
npm install react-native-reanimated@latest
# しかしMetroは古いキャッシュを使い続ける
npm start # ← 古いBabelプラグインの出力を使用
原因: Metroバンドラーがキャッシュをクリアしていない
# JSパッケージは更新した
npm install react-native-reanimated@3.16.7
# しかしネイティブコードは古いまま
# pod install を忘れた、または
# Xcodeの古いビルドキャッシュが残っている
原因: ネイティブ側のリビルドが必要
まず、どのパッケージがReanimatedを使っているか確認します:
# yarnの場合
yarn why react-native-reanimated
# npmの場合
npm ls react-native-reanimated
出力例で複数バージョンが表示されたら、それが原因です。
package.jsonに以下を追加して、プロジェクト全体で単一バージョンを強制します:
{
"dependencies": {
"react-native-reanimated": "^3.16.7"
},
"resolutions": {
"react-native-reanimated": "3.16.7"
}
}
{
"dependencies": {
"react-native-reanimated": "^3.16.7"
},
"overrides": {
"react-native-reanimated": "3.16.7"
}
}
ここが最も重要です。React Nativeでは複数のキャッシュが存在します:
# 1. node_modulesの削除と再インストール
rm -rf node_modules
rm -rf package-lock.json # または yarn.lock
npm install # または yarn
# 2. Metro Bundlerのキャッシュクリア
npm start -- --reset-cache
# Expoの場合
npx expo start -c
# 3. iOSのキャッシュクリア
cd ios
rm -rf Pods
rm -rf Podfile.lock
rm -rf ~/Library/Developer/Xcode/DerivedData
pod install
cd ..
# 4. Androidのキャッシュクリア
cd android
./gradlew clean
cd ..
Reanimatedのプラグインは必ず最後に記述する必要があります:
module.exports = {
presets: ['module:@react-native/babel-preset'],
plugins: [
// 他のプラグインは先に書く
'@babel/plugin-transform-runtime',
// Reanimatedは必ず最後!
'react-native-reanimated/plugin',
],
};
# iOSの場合
npx react-native run-ios --reset-cache
# Androidの場合
npx react-native run-android
# Expoの場合(Development Build)
npx expo run:ios
# または
npx expo run:android
resolutions/overridesでバージョンを統一Webの感覚で「npm installしたら終わり」と思っていると、React Nativeでは必ずハマります。ネイティブアプリは複数のレイヤーで構成されていることを常に意識しましょう。