Rorkで生成したアプリを実機で動かしていると、「スワイプしているのに画面が動かない」「ボタンを押しても無反応」という問題に出くわすことがあります。厄介なのは、コンソールにはエラーが一切出ないケースが多いことです。
こういった現象は、React NativeのGestureHandler周りの設定漏れや、コンポーネントの重なりによる競合が原因であることがほとんどです。RorkのAIは機能ロジックを正確に生成しますが、タッチイベントのレイヤー設計は人間が確認する必要がある部分でもあります。
実際によく起きる5つのパターンと、それぞれの修正方法を順番にご紹介します。
原因①:GestureHandlerRootViewが設定されていない
Expo SDK 50以降、react-native-gesture-handler を使う場合はアプリのルートを GestureHandlerRootView でラップすることが必須です。Rorkが生成するコードでは、スワイプ可能なカードやドラッグ&ドロップを含む画面を作った際にこの設定が省略されることがあります。
// ❌ よくある状態:ルートがラップされていない
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import RootNavigator from './navigation/RootNavigator';
export default function App() {
return (
<NavigationContainer>
<RootNavigator />
</NavigationContainer>
);
}
// ✅ 修正後:GestureHandlerRootViewでラップする
import React from 'react';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { NavigationContainer } from '@react-navigation/native';
import RootNavigator from './navigation/RootNavigator';
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<NavigationContainer>
<RootNavigator />
</NavigationContainer>
</GestureHandlerRootView>
);
}style={{ flex: 1 }} を忘れると画面が縮んで表示が崩れることがあるので一緒に設定してください。この一行の追加で、スワイプ系のジェスチャーがまるごと動き出すことは珍しくありません。
原因②:透明なViewがタッチを横取りしている
zIndex や position: 'absolute' でコンポーネントを重ねた場合、目に見えない上位レイヤーのViewがタッチを横取りしてしまうことがあります。モーダルやオーバーレイ、グラデーション背景をRorkで生成した際に起きやすいパターンです。
// ❌ 問題のある状態:全画面の透明Viewがタッチを奪っている
<View style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}>
{/* 背景グラデーションなど */}
</View>
<TouchableOpacity onPress={handlePress}>
<Text>押してもなぜか反応しない</Text>
</TouchableOpacity>
// ✅ 修正:pointerEventsを設定してタッチを透過させる
<View
style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
pointerEvents="none"
>
{/* 背景だけのView — タッチは下のコンポーネントへ */}
</View>
<TouchableOpacity onPress={handlePress}>
<Text>正常に反応するようになった</Text>
</TouchableOpacity>デバッグ時は疑わしいコンポーネントを一時的に display: 'none' にしてジェスチャーが効くか確認するのが一番早いです。動くようになったら、元に戻して pointerEvents="none" を追加する、というフローで原因を特定できます。
原因③:ScrollViewとスワイプジェスチャーが競合している
ScrollView内でスワイプカードやスライダーを使うと、縦スクロールと横スワイプのどちらを優先すべきかでReact Nativeが迷い、どちらも中途半端にしか動かない現象が起きます。
// ✅ iOS向け:directionalLockEnabledで一方向にロック
<ScrollView directionalLockEnabled={true}>
<SwipeableCard />
</ScrollView>
// ✅ GestureHandlerのPanGestureで方向を明示する方法
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';
export function SwipeCard() {
const translateX = useSharedValue(0);
const swipeGesture = Gesture.Pan()
.activeOffsetX([-10, 10]) // 横10px以上動いたら認識
.failOffsetY([-5, 5]) // 縦に5px動いたらスクロールに譲る
.onUpdate((event) => {
translateX.value = event.translationX;
})
.onEnd(() => {
translateX.value = withSpring(0);
});
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ translateX: translateX.value }],
}));
return (
<GestureDetector gesture={swipeGesture}>
<Animated.View style={[styles.card, animatedStyle]}>
{/* カードの中身 */}
</Animated.View>
</GestureDetector>
);
}activeOffsetX と failOffsetY の組み合わせがポイントです。これを設定するだけで、縦スクロールと横スワイプの競合がほとんどのケースで解消します。
Rorkでアニメーションのより高度な実装をしたい場合は、Reanimated × Gesture Handlerで作るスワイプアニメーション完全ガイドも参考にしてください。
原因④:Androidでタッチの反応が遅い・効かないように見える
Androidでは TouchableNativeFeedback や Pressable のrippleエフェクトが、タッチの応答を体感的に遅く見せることがあります。これ自体はバグではありませんが、カード型UIのスワイプと組み合わさると「タッチが効かない」と誤解されやすいです。
// ✅ Pressableでタッチ遅延を最小化する
<Pressable
onPress={handlePress}
android_ripple={{ color: 'rgba(0,0,0,0.1)' }}
unstable_pressDelay={0} // タッチ認識の遅延をゼロに
style={({ pressed }) => [
styles.card,
{ opacity: pressed ? 0.85 : 1 },
]}
>
<Text>レスポンスの良いボタン</Text>
</Pressable>unstable_pressDelay={0} は名前に「unstable」が含まれていますが、実用上は安定して動作します。ただし将来のReact Nativeバージョンで挙動が変わる可能性があるため、アップデート時には確認が必要です。
また、Androidの hitSlop を設定してタッチ範囲を広げることも有効です。
<Pressable
onPress={handlePress}
hitSlop={{ top: 8, bottom: 8, left: 8, right: 8 }}
>
<Text>タッチしやすいボタン</Text>
</Pressable>アイコンボタンや小さなUIパーツが「押せない」と感じる場合は、hitSlop を試してみてください。
原因⑤:Modal内のジェスチャーが検知されない
React NativeのModalコンポーネント内でGestureHandlerを使う場合は、追加の設定が必要です。ModalはネイティブのWindowに描画されるため、アプリルートに置いた GestureHandlerRootView のスコープ外になってしまいます。
// ❌ Modal内のスワイプが効かない状態
import { Modal } from 'react-native';
<Modal visible={isVisible} transparent animationType="slide">
<SwipeableBottomSheet /> {/* ← ジェスチャーが認識されない */}
</Modal>
// ✅ Modal内でも個別にGestureHandlerRootViewをラップする
import { Modal } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
<Modal visible={isVisible} transparent animationType="slide">
<GestureHandlerRootView style={{ flex: 1 }}>
<SwipeableBottomSheet /> {/* ← 正常に動作する */}
</GestureHandlerRootView>
</Modal>ボトムシートをModalで実装している場合に特に起きやすいパターンです。@gorhom/bottom-sheet などのサードパーティライブラリを使っている場合も同様で、ライブラリのドキュメントにModal対応の設定が記載されていることが多いので確認してみてください。
それでも解決しない場合のチェックリスト
上記の5つで解決しない場合は、以下を順番に確認してください。
react-native-gesture-handlerとreact-native-reanimatedのバージョンが互換性を持っているか(package.jsonで照合)- Expo SDKのバージョンと各ライブラリが対応しているか(Expo公式の互換性テーブルを確認)
- Expo GoではなくEAS Buildした実機ビルドで試したか(Expo GoはGesture Handlerの挙動が本番と異なる場合がある)
- iOSとAndroidで挙動が違う場合は、プラットフォーム別の処理が必要なサインです
Rorkのプロンプトで「ジェスチャーが動かない、GestureHandlerRootViewを確認してほしい」と具体的に伝えると、AIが的確な修正を提案してくれることがあります。エラーが出ていない分、漠然と「動かない」と伝えるだけでは原因を特定しにくいので、この記事で絞り込んだ仮説を一緒に伝えると解決が早まります。
アプリの品質をさらに上げるための次のステップとして、Rorkアプリのエラーハンドリングとクラッシュ防止の基本もあわせて読んでみてください。