sue@blog ~ /posts/react-native-reanimated
$ cd ../
$ cat post.metadata

React Native Reanimated
バージョン不一致エラー完全解説

date: 2026-02-28 React Native Reanimated Troubleshooting
React経験者がReact Nativeで必ずハマる「Mismatch between JavaScript code version and Reanimated Babel plugin version」の原因と解決策を詳しく解説。

このエラーに遭遇したあなたへ

「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 Native Reanimatedとは?

Webの世界との違い

Reactでアニメーションを実装する場合、以下のような選択肢があります:

これらはすべてブラウザのレンダリングエンジン上で動作します。

一方、React NativeではネイティブUI(iOS: UIKit、Android: Android View)を操作する必要があります。ここで登場するのが React Native Reanimated です。

なぜReanimatedが必要なのか

React Nativeのアーキテクチャを図解すると:

react-native-architecture
┌─────────────────────────────────────────────────────────┐
│                    JavaScript Thread                     │
│   (あなたのReactコード、ビジネスロジック、状態管理)        │
└────────────────────────┬────────────────────────────────┘
                         │ Bridge(JSON経由の通信)
                         ▼
┌─────────────────────────────────────────────────────────┐
│                      Native Thread                       │
│      (UIKit / Android View - 実際のUI描画)               │
└─────────────────────────────────────────────────────────┘

通常、JavaScriptとネイティブ間の通信はBridgeを経由します。この通信は非同期で、60fpsのスムーズなアニメーションには遅すぎることがあります。

Reanimatedの解決策:
reanimated-architecture
┌─────────────────────────────────────────────────────────┐
│                    JavaScript Thread                     │
│   Reanimated: アニメーション定義を「Worklet」として転送   │
└────────────────────────┬────────────────────────────────┘
                         │ Worklet(コンパイル済みコード)
                         ▼
┌─────────────────────────────────────────────────────────┐
│                      UI Thread                           │
│   Workletがネイティブ側で直接実行(Bridgeバイパス)       │
└─────────────────────────────────────────────────────────┘

エラーの正体:なぜバージョン不一致が起きるのか

Reanimatedの3層構造

ここがReact経験者には分かりにくいポイントです。Reanimatedは3つの異なるレイヤーで構成されています:

reanimated-3-layers
┌─────────────────────────────────────────────────────────┐
│   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との決定的な違い

項目 Web (React) React Native
インストール npm install → すぐ使える npm install → Babel設定 → pod install → ネイティブビルド
バンドラー Webpack / Vite Metro Bundler
キャッシュ ブラウザキャッシュ Metro + ネイティブビルド + DerivedData
ネイティブ連携 不要 CocoaPods (iOS) / Gradle (Android)

エラーが発生する典型的なシナリオ

シナリオ1: 依存パッケージの競合

node_modules の構造
your-app/
├── node_modules/
│   ├── react-native-reanimated@3.16.7 ← あなたがインストール
│   └── some-navigation-library/
│       └── node_modules/
│           └── react-native-reanimated@3.10.1 ← ライブラリが内包

原因: 他のライブラリが古いReanimatedを内部に持っている

シナリオ2: Metro Bundlerのキャッシュ

metro-cache-issue
# パッケージを更新
npm install react-native-reanimated@latest

# しかしMetroは古いキャッシュを使い続ける
npm start  # ← 古いBabelプラグインの出力を使用

原因: Metroバンドラーがキャッシュをクリアしていない

シナリオ3: ネイティブビルドの未更新

native-build-stale
# JSパッケージは更新した
npm install react-native-reanimated@3.16.7

# しかしネイティブコードは古いまま
# pod install を忘れた、または
# Xcodeの古いビルドキャッシュが残っている

原因: ネイティブ側のリビルドが必要

解決方法:ステップバイステップ

1 バージョンの確認

まず、どのパッケージがReanimatedを使っているか確認します:

check-versions
# yarnの場合
yarn why react-native-reanimated

# npmの場合
npm ls react-native-reanimated

出力例で複数バージョンが表示されたら、それが原因です。

2 バージョンの統一(resolutions/overrides)

package.jsonに以下を追加して、プロジェクト全体で単一バージョンを強制します:

package.json (yarn)
{
  "dependencies": {
    "react-native-reanimated": "^3.16.7"
  },
  "resolutions": {
    "react-native-reanimated": "3.16.7"
  }
}
package.json (npm)
{
  "dependencies": {
    "react-native-reanimated": "^3.16.7"
  },
  "overrides": {
    "react-native-reanimated": "3.16.7"
  }
}
3 キャッシュの完全クリア

ここが最も重要です。React Nativeでは複数のキャッシュが存在します:

cache-clear-all
# 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 ..
4 babel.config.jsの確認

Reanimatedのプラグインは必ず最後に記述する必要があります:

babel.config.js
module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: [
    // 他のプラグインは先に書く
    '@babel/plugin-transform-runtime',

    // Reanimatedは必ず最後!
    'react-native-reanimated/plugin',
  ],
};
5 アプリの再ビルド
rebuild
# 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

まとめ:解決の3原則

解決の3原則

Webの感覚で「npm installしたら終わり」と思っていると、React Nativeでは必ずハマります。ネイティブアプリは複数のレイヤーで構成されていることを常に意識しましょう。

参考リンク

$ _|