# React Nativeの面接でよく聞かれる質問30選: 2026年完全ガイド > React Nativeの面接で頻繁に問われる30の質問を厳選しました。コード例を交えた詳細な解説で、モバイル開発職の獲得を目指せます。 - Published: 2026-02-01 - Updated: 2026-04-27 - Author: SharpSkill - Tags: react native interview, mobile interview, react native questions, javascript, technical interview - Reading time: 20 min --- React Nativeの技術面接では、クロスプラットフォームのモバイル開発スキル、iOSとAndroid固有の知識、パフォーマンス設計が評価されます。本ガイドでは最も頻出する30問を取り上げ、効果的な準備のために詳細な回答とコード例を示します。 > **準備のためのアドバイス** > > 本記事の質問は基礎から発展的な概念までを網羅しています。React Nativeのアーキテクチャを理解し、Web版Reactとの相違点を把握することが面接突破の鍵となります。 ## React Nativeの基礎 ### 1. ReactとReact Nativeの違いは何ですか? ReactはWebインターフェース構築のためのライブラリですが、React NativeはiOSとAndroid向けのネイティブモバイルアプリ開発を可能にする技術です。 根本的な違いはレンダリング方式にあります。ReactはVirtual DOMを使ってHTML要素に変換しますが、React Nativeはブリッジを介して各プラットフォームのネイティブコンポーネントと通信します。 ```jsx // React (Web) - uses HTML elements function WebComponent() { return (
Web text
) } // React Native - uses native components import { View, Text, TouchableOpacity, StyleSheet } from 'react-native' function NativeComponent() { return ( Native text Press ) } const styles = StyleSheet.create({ container: { flex: 1, padding: 16 } }) ``` React Nativeのコンポーネントは、iOSではUIView、Androidではandroid.viewに変換され、ネイティブ品質のパフォーマンスを実現します。 ### 2. React Nativeのアーキテクチャはどのように動作しますか? React Nativeは、JavaScript層、Bridge層(新アーキテクチャではJSI)、Native層という三層構造を採用しています。 JavaScriptコードはJSエンジン(HermesまたはJavaScriptCore)上で実行されます。ネイティブコードとの通信は、旧アーキテクチャではJSONシリアライゼーションを介して行われ、新アーキテクチャではJSI(JavaScript Interface)を通じて直接行われます。 ```jsx // Old architecture: asynchronous communication via Bridge // The Bridge serializes messages as JSON between JS and Native // New architecture (Fabric + TurboModules) // JSI enables synchronous direct calls to native modules // Example TurboModule usage import { TurboModuleRegistry } from 'react-native' // Synchronous access to native module const DeviceInfo = TurboModuleRegistry.get('DeviceInfo') const deviceName = DeviceInfo.getDeviceName() // Synchronous call // With Fabric, rendering is smoother // Components can be created synchronously // Reducing jank during animations ``` 新アーキテクチャはJSONシリアライゼーションを排除し、同期的な呼び出しを可能にすることで、パフォーマンスを大幅に改善します。 ### 3. Metroバンドラーとは何ですか? MetroはReact Nativeで使われるJavaScriptバンドラーであり、ソースコードをモバイル実行向けに最適化されたバンドルへ変換します。 Metroはモジュール解決、コード変換(Babel経由)、開発時のホットリロードを担当します。 ```javascript // metro.config.js const { getDefaultConfig } = require('expo/metro-config') const config = getDefaultConfig(__dirname) // Custom configuration config.resolver.assetExts.push('db') // Add extensions config.resolver.sourceExts.push('cjs') // CommonJS support // Transformer configuration config.transformer.babelTransformerPath = require.resolve( 'react-native-svg-transformer' ) // Production optimizations config.transformer.minifierConfig = { keep_classnames: true, keep_fnames: true, mangle: { keep_classnames: true, keep_fnames: true } } module.exports = config ``` MetroはFast Refreshに対応しており、アプリの状態を失わずに即座に変更を反映できます。 ### 4. StyleSheet.createとその利点を説明してください `StyleSheet.create`はスタイルを検証し、数値参照に変換することで最適化を行い、ブリッジ通信のオーバーヘッドを削減します。 ```jsx // ❌ Inline styles - recreated on every render function BadExample() { return ( Title ) } // ✅ StyleSheet.create - optimized and validated const styles = StyleSheet.create({ container: { flex: 1, padding: 16, backgroundColor: '#fff' }, title: { fontSize: 18, fontWeight: 'bold' }, // Style composition row: { flexDirection: 'row', alignItems: 'center', gap: 8 } }) function GoodExample() { return ( Title {/* Style combination */} Content ) } // StyleSheet.absoluteFillObject for absolute positioning const overlayStyles = StyleSheet.create({ overlay: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(0,0,0,0.5)' } }) ``` ### 5. WebのFlexboxとReact Nativeの違いは何ですか? React NativeもFlexboxを使用しますが、縦方向のモバイル画面に適応するため、Webとは異なるデフォルト値が設定されています。 ```jsx // Key differences from web const styles = StyleSheet.create({ container: { // flexDirection: 'column' by default (vs 'row' on web) // alignItems: 'stretch' by default flex: 1 }, // React Native Flexbox row: { flexDirection: 'row', // Horizontal justifyContent: 'space-between', // Main axis alignItems: 'center', // Cross axis flexWrap: 'wrap', // Line wrapping gap: 8 // Supported since RN 0.71 }, // Flex grow/shrink flexItem: { flex: 1, // Equivalent to flex: 1 1 0 flexGrow: 1, // Grow to fill flexShrink: 0, // Don't shrink flexBasis: 100 // Base size }, // Absolute positioning absolute: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 } }) // Practical example: card with image and content function Card() { return ( Title Description ) } const cardStyles = StyleSheet.create({ container: { flexDirection: 'row', backgroundColor: '#fff', borderRadius: 8, overflow: 'hidden' }, image: { width: 100, height: 100 }, content: { flex: 1, // Takes remaining space padding: 12, justifyContent: 'center' }, title: { fontSize: 16, fontWeight: '600' }, description: { fontSize: 14, color: '#666' } }) ``` ## ナビゲーションとコンポーネント ### 6. React Navigationでナビゲーションをどう実装しますか? React NativeにおけるナビゲーションのデファクトスタンダードはReact Navigationです。モバイル特有のパターンに合わせた複数のナビゲーター種別が用意されています。 ```jsx // Installing dependencies // npm install @react-navigation/native @react-navigation/native-stack // npm install react-native-screens react-native-safe-area-context import { NavigationContainer } from '@react-navigation/native' import { createNativeStackNavigator } from '@react-navigation/native-stack' import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' // TypeScript typing for navigation params type RootStackParamList = { Home: undefined Profile: { userId: string } Settings: { section?: string } } const Stack = createNativeStackNavigator() const Tab = createBottomTabNavigator() // Tab navigation function TabNavigator() { return ( ({ tabBarIcon: ({ focused, color, size }) => { // Dynamic icon based on tab const iconName = route.name === 'Home' ? 'home' : 'settings' return }, tabBarActiveTintColor: '#007AFF', tabBarInactiveTintColor: 'gray' })} > ) } // Stack navigation function App() { return ( ({ title: `Profile ${route.params.userId}` })} /> ) } ``` ### 7. FlatListでパフォーマンスの高いリストをどう扱いますか? `FlatList`は自動仮想化により、画面に表示されている要素のみを描画する長尺リスト向けの最適化されたコンポーネントです。 ```jsx import { FlatList, RefreshControl } from 'react-native' function ProductList() { const [products, setProducts] = useState([]) const [refreshing, setRefreshing] = useState(false) const [loading, setLoading] = useState(false) // Initial loading const fetchProducts = async (page = 1) => { const response = await api.getProducts(page) return response.data } // Pull-to-refresh const onRefresh = useCallback(async () => { setRefreshing(true) const data = await fetchProducts(1) setProducts(data) setRefreshing(false) }, []) // Infinite pagination const loadMore = useCallback(async () => { if (loading) return setLoading(true) const nextPage = Math.ceil(products.length / 20) + 1 const data = await fetchProducts(nextPage) setProducts(prev => [...prev, ...data]) setLoading(false) }, [products.length, loading]) // Item rendering const renderItem = useCallback(({ item }) => ( ), []) // Key extraction const keyExtractor = useCallback((item) => item.id.toString(), []) // Item separator const ItemSeparator = useCallback(() => ( ), []) return ( } // Infinite pagination onEndReached={loadMore} onEndReachedThreshold={0.5} ListFooterComponent={loading ? : null} // Empty list ListEmptyComponent={} /> ) } ``` > **FlatListの最適化** > > `renderItem`は必ず`useCallback`でメモ化し、重いコンポーネントは外部に切り出してください。`renderItem`内のインラインアロー関数は不要な再レンダリングの原因となります。 ### 8. TouchableOpacity、Pressable、TouchableHighlightの違いは何ですか? これらはタッチ操作を扱うコンポーネントですが、視覚的なフィードバックの方法が異なります。 ```jsx import { TouchableOpacity, TouchableHighlight, Pressable, StyleSheet } from 'react-native' function InteractionExamples() { return ( {/* TouchableOpacity: reduces opacity on touch */} console.log('Pressed')} style={styles.button} > TouchableOpacity {/* TouchableHighlight: adds background color */} console.log('Pressed')} style={styles.button} > TouchableHighlight {/* Pressable: modern API with more control */} console.log('Pressed')} onLongPress={() => console.log('Long press')} delayLongPress={500} style={({ pressed }) => [ styles.button, pressed && styles.buttonPressed ]} > {({ pressed }) => ( {pressed ? 'Pressed!' : 'Pressable'} )} {/* Pressable with hitSlop to enlarge touch area */} console.log('Pressed')} style={styles.smallButton} > Small button ) } const styles = StyleSheet.create({ container: { gap: 16, padding: 20 }, button: { backgroundColor: '#007AFF', padding: 16, borderRadius: 8, alignItems: 'center' }, buttonPressed: { backgroundColor: '#0056b3', transform: [{ scale: 0.98 }] }, textPressed: { color: '#fff' }, smallButton: { padding: 8, backgroundColor: '#eee' } }) ``` 新規プロジェクトでは、より柔軟な制御と一貫したAPIを提供する`Pressable`の利用が推奨されます。 ### 9. 滑らかなアニメーションをどう実装しますか? React Nativeには複数のアニメーションAPIがあります。組み込みのAnimatedと、より高性能なReanimatedです。 ```jsx import { Animated, Easing } from 'react-native' import Reanimated, { useSharedValue, useAnimatedStyle, withSpring, withTiming } from 'react-native-reanimated' // Animation with Animated (native API) function FadeInView({ children }) { const fadeAnim = useRef(new Animated.Value(0)).current useEffect(() => { Animated.timing(fadeAnim, { toValue: 1, duration: 500, easing: Easing.ease, useNativeDriver: true // Performant on UI thread }).start() }, []) return ( {children} ) } // Animation with Reanimated (recommended for complex animations) function BouncyButton() { const scale = useSharedValue(1) const animatedStyle = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }] })) const handlePressIn = () => { scale.value = withSpring(0.95, { damping: 10, stiffness: 400 }) } const handlePressOut = () => { scale.value = withSpring(1, { damping: 10, stiffness: 400 }) } return ( Press ) } // List animation with LayoutAnimation import { LayoutAnimation, UIManager, Platform } from 'react-native' // Enable on Android if (Platform.OS === 'android') { UIManager.setLayoutAnimationEnabledExperimental?.(true) } function AnimatedList() { const [items, setItems] = useState([]) const addItem = () => { // Configure animation before state change LayoutAnimation.configureNext(LayoutAnimation.Presets.spring) setItems(prev => [...prev, { id: Date.now() }]) } const removeItem = (id) => { LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) setItems(prev => prev.filter(item => item.id !== id)) } return (