RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/開発ツール
開発ツール/2026-05-06中級

Rorkアプリのアニメーションがカクつく — フレームドロップの根本原因を特定して直した手順

Rorkで生成されたアニメーションがカクつく問題の根本原因と修正手順を解説します。JSスレッドとUIスレッドの分離、useNativeDriverの使い方、フレームドロップの診断方法まで実践的にまとめました。

Rork515React Native209アニメーション10パフォーマンス30useNativeDriverトラブルシューティング77

Rorkで作ったアプリのアニメーションが、実機で確認するとカクカクします。そんな経験はないでしょうか。

プレビューでは問題なく動いているのに、TestFlightで試したら明らかにスムーズでない——個人開発をしていると、このギャップに気づくのは公開直前や公開後になりがちです。私自身、この問題に初めて直面したとき「Rorkが生成したコードだから仕方ない」と思い込んでそのままにしていた時期がありました。

ところが原因を調べてみると、多くの場合はたった1行の修正で解決できることがわかりました。フレームドロップが起きる根本的な仕組みと、診断から修正までの具体的な手順を実例とともに整理しました。

なぜアニメーションがカクつくのか — JSスレッドとUIスレッドの関係

React Nativeは、JavaScriptを処理するJSスレッドと、画面描画を担当するUIスレッドの2本柱で動いています。Rorkが生成するコードの多くはAnimated APIを使いますが、デフォルト設定ではアニメーションの計算がJSスレッド上で行われます。

問題は、JSスレッドがAPI通信やStateの更新など他の処理に追われると、アニメーションの計算が後回しになることです。60fpsを維持するには毎秒60回の計算が必要ですが、JSスレッドが詰まると1フレームが16.67msを超え、目に見えるカクつきとして現れます。

// ❌ Rorkが生成しがちなコード例 — JSスレッドで計算するためカクつく原因になる
const fadeAnim = useRef(new Animated.Value(0)).current;
 
Animated.timing(fadeAnim, {
  toValue: 1,
  duration: 300,
  // useNativeDriver が指定されていない(暗黙的にfalseになる)
}).start();

UIスレッドはJSスレッドとは独立して動くため、アニメーション計算をUIスレッドに委譲できれば、JSスレッドが混雑してもアニメーションはスムーズに動き続けます。

フレームドロップを診断する方法

修正の前に、まず本当にフレームドロップが起きているかを確認しましょう。React Nativeには開発ビルドで使えるパフォーマンスモニターが標準搭載されています。

実機でExpo開発ビルドを起動した状態で、メニューを開いて「Show Performance Monitor」を選択します。するとUI FPSとJS FPSの2つの数値がリアルタイムで表示されます。

見るべき数字:

  • UI FPSが60に近く、JS FPSだけが低下している場合はJSスレッドでアニメーション計算をしているサインです
  • 両方が低下している場合は、重いレンダリング処理が別の場所に潜んでいる可能性があります

Rork Companionを使っている場合は、コンソールログにAnimated: useNativeDriver was not specifiedという警告が出ていないかも確認してください。この警告が出ていれば、次の修正が直接効きます。

最もよくある原因と修正コード

useNativeDriver: true を追加する

Rorkが生成するコードで最も多いのは、useNativeDriverが未指定またはfalseになっているケースです。

// ✅ 修正後 — UIスレッドで計算し、JSスレッドの混雑に影響されない
const fadeAnim = useRef(new Animated.Value(0)).current;
 
Animated.timing(fadeAnim, {
  toValue: 1,
  duration: 300,
  useNativeDriver: true, // ← この1行を追加するだけ
}).start();
 
// 複数アニメーションの組み合わせも同様に指定する
Animated.parallel([
  Animated.timing(fadeAnim, { toValue: 1, duration: 300, useNativeDriver: true }),
  Animated.spring(slideAnim, { toValue: 0, useNativeDriver: true }),
]).start();

重要な制限: useNativeDriver: trueは、opacitytransform(translateX, translateY, scale, rotate)など、レイアウトを変えないプロパティにのみ使用できます。widthheightbackgroundColorなどレイアウト変更を伴うプロパティには使用できません。

// ❌ useNativeDriver: true を使えないプロパティ例(エラーになる)
Animated.timing(widthAnim, {
  toValue: 200,
  duration: 300,
  useNativeDriver: true, // width はネイティブドライバー非対応
}).start();
 
// ✅ 代替: transform.scaleX で横幅を変えているように見せる
Animated.timing(scaleAnim, {
  toValue: 2,
  duration: 300,
  useNativeDriver: true,
}).start();

② Reanimatedへの移行(複雑なアニメーションの場合)

スクロール連動アニメーションや、ジェスチャーと組み合わせた複雑な動きが必要な場合は、react-native-reanimatedを使う方が根本的な解決になります。Expoのマネージドワークフローではすでにインストール済みです。

// react-native-reanimated を使ったスクロール連動フェードイン
import Animated, {
  useAnimatedStyle,
  useSharedValue,
  withTiming,
} from 'react-native-reanimated';
 
function AnimatedCard() {
  const opacity = useSharedValue(0);
 
  useEffect(() => {
    opacity.value = withTiming(1, { duration: 400 });
  }, []);
 
  const animatedStyle = useAnimatedStyle(() => ({
    opacity: opacity.value,
  }));
 
  return (
    <Animated.View style={[styles.card, animatedStyle]}>
      {/* コンテンツ */}
    </Animated.View>
  );
}

ReanimatedのワークレットはデフォルトでUIスレッド上で直接実行されるため、JSスレッドを完全にバイパスします。スクロール連動やドラッグアニメーションでは、この差が体感として明確に現れます。

③ FlatListスクロール時にカクつく場合

アニメーション自体に問題がなく、スクロール時にカクつく場合は、FlatListのアイテムレンダリングが原因であることがほとんどです。

// ❌ スクロールのたびに重い計算が走るパターン
<FlatList
  data={items}
  renderItem={({ item }) => (
    <View style={[styles.item, { backgroundColor: item.color }]}>
      <Image source={{ uri: item.imageUrl }} />
      <Text>{item.title}</Text>
    </View>
  )}
/>
 
// ✅ React.memoでアイテムコンポーネントをメモ化する
const ItemComponent = React.memo(({ item }) => (
  <View style={[styles.item, { backgroundColor: item.color }]}>
    <Image source={{ uri: item.imageUrl }} />
    <Text>{item.title}</Text>
  </View>
));
 
<FlatList
  data={items}
  renderItem={({ item }) => <ItemComponent item={item} />}
  windowSize={5}         // 画面外の描画範囲を絞る
  initialNumToRender={8} // 初期表示件数を必要最小限に
  maxToRenderPerBatch={5} // 一度に追加するアイテム数を制限
/>

④ 画面遷移直後のカクつき — 重い処理を遷移完了後に遅延させる

画面遷移のアニメーション中にデータ取得や重い初期化を走らせると、遷移そのものがカクつきます。InteractionManagerを使うと、アニメーション完了後まで重い処理を遅延できます。

import { InteractionManager } from 'react-native';
 
useEffect(() => {
  const task = InteractionManager.runAfterInteractions(() => {
    // 遷移アニメーション完了後に実行される
    loadHeavyData();
  });
  return () => task.cancel();
}, []);

私のアプリでは、一覧→詳細の遷移でこのパターンに変えただけで「遷移の引っかかり」の体感が明確に変わりました。遷移直後にuseEffectで重い処理を即実行しているコードは、Rorkの生成コードに限らずよく見かける形なので、遷移系のカクつきではまずここを疑ってみてください。

Rorkへのプロンプトで最初から問題を防ぐ

修正よりも、最初から問題を発生させないプロンプトを使う方が効率的です。Rorkにアニメーションを追加させる際は、以下のように明示的に指示するとuseNativeDriverが最初から設定された状態でコードが生成されやすくなります。

「フェードインアニメーションを追加してください。
useNativeDriver: true を必ず使用し、60fps を維持できる実装にしてください。」

「スクロール連動のアニメーションは react-native-reanimated を使用してください。」

実際に試したところ、明示的に指定することで生成コードの品質が安定しました。指定なしだと、シンプルなケースではuseNativeDriverを付けてくれることもありますが、複雑なアニメーションでは省略されることがあります。

修正後の確認チェックリスト

修正後は以下を実機(TestFlightビルド)で確認してください。シミュレーターはパフォーマンスが実機と大きく異なるため、最終確認は必ず実機で行いましょう。

  • パフォーマンスモニターで UI FPSJS FPS が両方60近くを維持しているか
  • スクロール中もアニメーションがスムーズに動くか
  • コンソールに useNativeDriver was not specified 警告が出ていないか
  • 古い端末(iPhone XS相当)でも許容できるスムーズさか

アニメーションのスムーズさは、ユーザーがアプリの「質」を感じる重要な要素です。useNativeDriver: trueの追加という、たった1行の修正で体験が大きく変わるケースが多いので、カクつきが気になったらまずここを確認してみてください。同じ症状で悩んでいる方の助けになれば幸いです。

シェア

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

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

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

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-05-22
FlatList の onEndReached が連続発火して API を叩きすぎる問題の原因と対処
FlatList の onEndReached が画面遷移時や初期描画時に何度も呼ばれて、ページネーション API を多重に叩いてしまう問題。Rork で生成したリスト画面でも頻発するこの挙動の原因と、実運用で使える対処パターンを整理しました。
開発ツール2026-04-24
Rork アプリで Reanimated の worklet エラーが出たときに順番に疑う 6 つのポイント
Rork 生成コードに Reanimated を組み込んだ途端に出る worklet 関連のエラーを、babel プラグインの抜け漏れから closure キャプチャまで、現場でぶつかる順に切り分けていきます。
開発ツール2026-04-12
Rorkアプリが重い・遅い・フリーズする原因と解決法:パフォーマンストラブルシューティングガイド
Rorkで作ったアプリが重い・画面切替が遅い・フリーズするときの原因を体系的に診断し、実践的な解決策を解説します。React Native特有のパフォーマンス問題にも対応。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →