12月 21, 2025
37 分で読める

React Nativeジュニア開発者の面接質問と回答

interview
career-advice
job-search
entry-level
React Nativeジュニア開発者の面接質問と回答
Milad Bonakdar

Milad Bonakdar

著者

コンポーネント、Hooks、ナビゲーション、API通信、リスト、AsyncStorage、モバイル基礎を中心にReact Nativeジュニア面接を練習できます。


はじめに

React Nativeのジュニア面接では、Reactで簡単なモバイル画面を作れるか、ネイティブレンダリングを説明できるか、Hooksで状態を管理できるか、画面遷移、API通信、非機密データのローカル保存を扱えるかがよく見られます。よい回答は実務的です。何を使うのか、いつ避けるのか、iOSとAndroidでどんなトレードオフがあるのかを説明しましょう。

このガイドでは、初めてのReact Native職で出やすい質問を練習できます。ライブラリの細かい暗記よりも、Reactの基礎、主要コンポーネント、ナビゲーション、フォーム、リスト、API通信、ストレージ、モバイルのデバッグに集中しましょう。


Reactの基礎 (6つの質問)

1. React Nativeとは何ですか?Reactとの違いは何ですか?

回答:

  • React: Webユーザーインターフェースを構築するためのJavaScriptライブラリ
  • React Native: Reactを使用してネイティブモバイルアプリを構築するためのフレームワーク
  • 主な違い:
    • React Nativeは(DOMではなく)ネイティブコンポーネントにレンダリングする
    • Web APIの代わりにネイティブAPIを使用する
    • スタイリングのアプローチが異なる(CSSがなく、StyleSheetを使用する)
    • iOSとAndroidでプラットフォーム固有のコードを使用する
// React (Web)
import React from 'react';

function App() {
  return <div className="container">Hello Web</div>;
}

// React Native (Mobile)
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

function App() {
  return (
    <View style={styles.container}>
      <Text>Hello Mobile</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

希少度: 非常に一般的 難易度: 簡単


2. React Nativeのコアコンポーネントは何ですか?

回答: React Nativeは、ネイティブUI要素にマッピングされる組み込みコンポーネントを提供します。

  • View: コンテナコンポーネント(Webのdivのようなもの)
  • Text: テキストを表示(すべてのテキストはTextコンポーネント内にある必要がある)
  • Image: 画像を表示
  • ScrollView: スクロール可能なコンテナ
  • TextInput: テキスト入力フィールド
  • TouchableOpacity/Pressable: タッチ可能な要素
  • FlatList: 効率的なリストレンダリング
  • Button: 基本的なボタンコンポーネント
import {
  View,
  Text,
  Image,
  TextInput,
  TouchableOpacity,
  StyleSheet,
} from 'react-native';

function MyComponent() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Welcome</Text>
      <Image source={{ uri: 'https://example.com/image.jpg' }} style={styles.image} />
      <TextInput placeholder="Enter name" style={styles.input} />
      <TouchableOpacity style={styles.button} onPress={() => console.log('Pressed')}>
        <Text style={styles.buttonText}>Click Me</Text>
      </TouchableOpacity>
    </View>
  );
}

希少度: 非常に一般的 難易度: 簡単


3. ViewScrollViewの違いを説明してください。

回答:

  • View: 静的なコンテナ。画面の境界を超えるコンテンツはスクロールできません。
  • ScrollView: スクロール可能なコンテナ。すべての子を一度にレンダリングします(大きなリストではメモリを大量に消費する可能性があります)。
  • 使用するタイミング:
    • View: 画面に収まるレイアウトの場合
    • ScrollView: スクロール可能なコンテンツが少量の場合
    • FlatList: 大きなリストの場合(表示されているアイテムのみをレンダリングします)
// View - スクロール不可
<View style={{ height: 200 }}>
  <Text>Content 1</Text>
  <Text>Content 2</Text>
  {/* コンテンツが200pxを超えると、切り捨てられます */}
</View>

// ScrollView - スクロール可能
<ScrollView style={{ height: 200 }}>
  <Text>Content 1</Text>
  <Text>Content 2</Text>
  <Text>Content 3</Text>
  {/* すべてのコンテンツを表示するためにスクロールできます */}
</ScrollView>

// FlatList - 大きなリストに効率的
<FlatList
  data={items}
  renderItem={({ item }) => <Text>{item.name}</Text>}
  keyExtractor={item => item.id}
/>

希少度: 非常に一般的 難易度: 簡単


4. Reactフックとは何ですか?最も一般的に使用されるものはどれですか?

回答: フックは、関数コンポーネントで状態とライフサイクルの機能を使用できるようにする関数です。

  • 一般的なフック:
    • useState: コンポーネントの状態を管理
    • useEffect: 副作用を処理(データフェッチ、サブスクリプション)
    • useContext: コンテキスト値にアクセス
    • useCallback: 関数をメモ化
    • useMemo: 高価な計算をメモ化
    • useRef: DOM要素を参照するか、値を永続化
import React, { useState, useEffect } from 'react';
import { View, Text, Button } from 'react-native';

function Counter() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    console.log(`Count changed to: ${count}`);
    
    // クリーンアップ関数
    return () => {
      console.log('Cleanup');
    };
  }, [count]); // countが変更されたときに実行
  
  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={() => setCount(count + 1)} />
    </View>
  );
}

希少度: 非常に一般的 難易度: 簡単


5. useEffectフックとその依存配列について説明してください。

回答: useEffectは、レンダリング後に副作用を実行します。依存配列は、いつ実行するかを制御します。

  • 配列なし: すべてのレンダリング後に実行
  • 空の配列[]: 最初のレンダリング後に一度実行
  • 依存関係あり[dep1, dep2]: 依存関係が変更されたときに実行
import { useEffect, useState } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  
  // マウント時に一度実行
  useEffect(() => {
    console.log('Component mounted');
  }, []);
  
  // userIdが変更されたときに実行
  useEffect(() => {
    fetchUser(userId).then(data => setUser(data));
  }, [userId]);
  
  // すべてのレンダリング後に実行(これは避ける)
  useEffect(() => {
    console.log('Rendered');
  });
  
  // クリーンアップ関数
  useEffect(() => {
    const subscription = subscribeToUpdates();
    
    return () => {
      subscription.unsubscribe(); // アンマウント時にクリーンアップ
    };
  }, []);
  
  return <Text>{user?.name}</Text>;
}

希少度: 非常に一般的 難易度: 中程度


6. 仮想DOMとは何ですか?Reactはどのように使用しますか?

回答: Virtual DOMはWeb版Reactの概念です。Reactは軽量なUIツリーを保持し、状態変更後に差分を比較して、変わった部分だけを更新します。React Nativeでも同じreconciliationの考え方は使われますが、最終的な出力はブラウザDOMではなくネイティブビューです。

  • 面接で伝えるポイント:
    1. 状態が変わると、影響を受けるコンポーネントが再レンダリングされる
    2. Reactが新しいコンポーネントツリーと前のツリーを比較する
    3. React Nativeが必要な更新をネイティブUIコンポーネントに適用する
    4. 安定したkey、適切なstate配置、必要な場合だけのメモ化で最適化する
  • 重要な補足: React NativeはHTMLやブラウザDOMを更新しません。

希少度: 一般的 難易度: 簡単


コンポーネントとプロパティ (4つの質問)

7. PropsとStateの違いは何ですか?

回答:

  • Props:
    • 親から子に渡される
    • 読み取り専用(不変)
    • コンポーネントの構成に使用
  • State:
    • コンポーネント内で管理される
    • 可変(変更可能)
    • 動的データに使用
// 親コンポーネント
function ParentComponent() {
  const [count, setCount] = useState(0);
  
  return (
    <ChildComponent 
      title="Counter"  // Props
      count={count}    // Props
      onIncrement={() => setCount(count + 1)}  // Props
    />
  );
}

// 子コンポーネント
function ChildComponent({ title, count, onIncrement }) {
  // propsは変更できません
  // title = "New Title"; // エラー!
  
  return (
    <View>
      <Text>{title}</Text>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={onIncrement} />
    </View>
  );
}

希少度: 非常に一般的 難易度: 簡単


8. 関数コンポーネントとクラスコンポーネントの違いは何ですか?

回答:

  • 関数コンポーネント:
    • よりシンプルな構文
    • 状態とライフサイクルにフックを使用
    • 現代のReactで推奨
  • クラスコンポーネント:
    • 古いアプローチ
    • this.stateとライフサイクルメソッドを使用
    • まだサポートされていますが、一般的ではありません
// 関数コンポーネント (現代的)
function Welcome({ name }) {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    console.log('Mounted');
  }, []);
  
  return <Text>Hello, {name}</Text>;
}

// クラスコンポーネント (レガシー)
class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }
  
  componentDidMount() {
    console.log('Mounted');
  }
  
  render() {
    return <Text>Hello, {this.props.name}</Text>;
  }
}

希少度: 一般的 難易度: 簡単


9. 子コンポーネントから親コンポーネントにデータを渡すにはどうすればよいですか?

回答: プロパティとして渡されるコールバック関数を使用します。

// 親コンポーネント
function ParentComponent() {
  const [message, setMessage] = useState('');
  
  const handleMessageFromChild = (msg) => {
    setMessage(msg);
  };
  
  return (
    <View>
      <Text>Message from child: {message}</Text>
      <ChildComponent onSendMessage={handleMessageFromChild} />
    </View>
  );
}

// 子コンポーネント
function ChildComponent({ onSendMessage }) {
  const [input, setInput] = useState('');
  
  const sendMessage = () => {
    onSendMessage(input); // 親の関数を呼び出す
  };
  
  return (
    <View>
      <TextInput value={input} onChangeText={setInput} />
      <Button title="Send to Parent" onPress={sendMessage} />
    </View>
  );
}

希少度: 非常に一般的 難易度: 簡単


10. keyプロパティとは何ですか?なぜ重要ですか?

回答: keyプロパティは、Reactがリスト内でどのアイテムが変更、追加、または削除されたかを識別するのに役立ちます。

  • 目的: レンダリングのパフォーマンスを最適化
  • 要件: 兄弟間で一意である必要があり、安定している必要があります(リストが変更される可能性がある場合はインデックスを使用しないでください)
// 良い例 - 一意のIDを使用
function UserList({ users }) {
  return (
    <FlatList
      data={users}
      keyExtractor={item => item.id} // 一意のキー
      renderItem={({ item }) => <Text>{item.name}</Text>}
    />
  );
}

// 悪い例 - インデックスを使用 (リストが変更される可能性がある場合は避ける)
function BadList({ items }) {
  return (
    <View>
      {items.map((item, index) => (
        <Text key={index}>{item}</Text> // インデックスを使用しないでください
      ))}
    </View>
  );
}

// 良い例 - 一意のプロパティを使用
function GoodList({ items }) {
  return (
    <View>
      {items.map(item => (
        <Text key={item.id}>{item.name}</Text>
      ))}
    </View>
  );
}

希少度: 非常に一般的 難易度: 簡単


スタイリングとレイアウト (3つの質問)

11. React Nativeでコンポーネントをスタイルするにはどうすればよいですか?

回答: React Nativeは、CSSではなくJavaScriptオブジェクトをスタイリングに使用します。

  • StyleSheet API: 最適化されたスタイルを作成
  • インラインスタイル: 直接的なスタイルオブジェクト(パフォーマンスが低い)
  • Flexbox: デフォルトのレイアウトシステム
import { View, Text, StyleSheet } from 'react-native';

function StyledComponent() {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Title</Text>
      <Text style={[styles.text, styles.bold]}>Multiple styles</Text>
      <Text style={{ color: 'red' }}>Inline style</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
  },
  text: {
    fontSize: 16,
    color: '#666',
  },
  bold: {
    fontWeight: 'bold',
  },
});

希少度: 非常に一般的 難易度: 簡単


12. React NativeのFlexboxについて説明してください。

回答: Flexboxは、React Nativeの主要なレイアウトシステムです。

  • 主なプロパティ:
    • flexDirection: rowまたはcolumn(デフォルト: column
    • justifyContent: 主軸に沿って配置
    • alignItems: 交差軸に沿って配置
    • flex: 比例サイズ設定
const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'row', // 水平レイアウト
    justifyContent: 'space-between', // アイテムを均等に配置
    alignItems: 'center', // 垂直方向に中央揃え
  },
  box1: {
    flex: 1, // スペースの1/3を占有
    backgroundColor: 'red',
  },
  box2: {
    flex: 2, // スペースの2/3を占有
    backgroundColor: 'blue',
  },
});

function FlexExample() {
  return (
    <View style={styles.container}>
      <View style={styles.box1} />
      <View style={styles.box2} />
    </View>
  );
}

希少度: 非常に一般的 難易度: 中程度


13. marginpaddingの違いは何ですか?

回答:

  • Padding: コンポーネントの内側のスペース(コンテンツと境界線の間)
  • Margin: コンポーネントの外側のスペース(コンポーネントと隣接要素の間)
const styles = StyleSheet.create({
  box: {
    margin: 20,        // 外側のスペース
    padding: 10,       // 内側のスペース
    backgroundColor: 'lightblue',
  },
  // 特定の側面
  specificBox: {
    marginTop: 10,
    marginBottom: 20,
    paddingLeft: 15,
    paddingRight: 15,
  },
  // 水平方向と垂直方向
  shorthand: {
    marginHorizontal: 20,  // 左と右
    marginVertical: 10,    // 上と下
    paddingHorizontal: 15,
    paddingVertical: 5,
  },
});

希少度: 一般的 難易度: 簡単


ナビゲーション (3つの質問)

14. React Navigationとは何ですか?どのように使用しますか?

回答: React Navigationは、React Nativeで最も人気のあるナビゲーションライブラリです。

  • 種類:
    • Stack Navigator: 画面スタック(プッシュ/ポップ)
    • Tab Navigator: 下部のタブ
    • Drawer Navigator: サイドドロワーメニュー
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

function HomeScreen({ navigation }) {
  return (
    <View>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details', { itemId: 42 })}
      />
    </View>
  );
}

function DetailsScreen({ route, navigation }) {
  const { itemId } = route.params;
  
  return (
    <View>
      <Text>Details Screen</Text>
      <Text>Item ID: {itemId}</Text>
      <Button title="Go Back" onPress={() => navigation.goBack()} />
    </View>
  );
}

希少度: 非常に一般的 難易度: 中程度


15. 画面間でパラメータを渡すにはどうすればよいですか?

回答: データには、2番目のパラメータを指定してnavigate関数を使用します。

// パラメータを使用してナビゲート
function HomeScreen({ navigation }) {
  const user = { id: 1, name: 'John', email: '[email protected]' };
  
  return (
    <Button
      title="View Profile"
      onPress={() => navigation.navigate('Profile', { user })}
    />
  );
}

// パラメータを受け取る
function ProfileScreen({ route }) {
  const { user } = route.params;
  
  return (
    <View>
      <Text>Name: {user.name}</Text>
      <Text>Email: {user.email}</Text>
    </View>
  );
}

// パラメータを更新
function EditScreen({ navigation }) {
  const updateUser = () => {
    navigation.setParams({ user: updatedUser });
  };
  
  return <Button title="Update" onPress={updateUser} />;
}

希少度: 非常に一般的 難易度: 簡単


16. ナビゲーションオプションとは何ですか?ヘッダーをカスタマイズするにはどうすればよいですか?

回答: ナビゲーションオプションは、画面の外観と動作を制御します。

function HomeScreen({ navigation }) {
  useEffect(() => {
    navigation.setOptions({
      title: 'My Home',
      headerStyle: {
        backgroundColor: '#f4511e',
      },
      headerTintColor: '#fff',
      headerTitleStyle: {
        fontWeight: 'bold',
      },
      headerRight: () => (
        <Button title="Info" onPress={() => alert('Info')} />
      ),
    });
  }, [navigation]);
  
  return <View><Text>Home</Text></View>;
}

// またはナビゲーターで設定
<Stack.Screen
  name="Home"
  component={HomeScreen}
  options={{
    title: 'My Home',
    headerStyle: { backgroundColor: '#f4511e' },
    headerTintColor: '#fff',
  }}
/>

希少度: 一般的 難易度: 簡単


データとストレージ (4つの質問)

17. React NativeでAPIからデータをフェッチするにはどうすればよいですか?

回答: fetch APIまたはAxiosなどのライブラリを使用します。

import { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';

function UserList() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    fetchUsers();
  }, []);
  
  const fetchUsers = async () => {
    try {
      const response = await fetch('https://api.example.com/users');
      
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      
      const data = await response.json();
      setUsers(data);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };
  
  if (loading) return <ActivityIndicator />;
  if (error) return <Text>Error: {error}</Text>;
  
  return (
    <FlatList
      data={users}
      renderItem={({ item }) => <Text>{item.name}</Text>}
      keyExtractor={item => item.id.toString()}
    />
  );
}

希少度: 非常に一般的 難易度: 中程度


18. AsyncStorageとは何ですか?どのように使用しますか?

回答: AsyncStorageは、小さく非機密なデータを保存するための非同期key-valueストレージです。

  • 向いている用途: テーマ設定、オンボーディングのフラグ、キャッシュしたJSON、簡単なユーザー設定
  • 避ける用途: 認証トークン、APIキー、パスワード、大きなデータセット、複雑なクエリが必要なデータ
  • 機密データの場合: iOS KeychainやAndroidの暗号化ストレージなど、保守されているライブラリ経由の安全なストレージを使います
import AsyncStorage from '@react-native-async-storage/async-storage';

const savePreference = async (theme) => {
  await AsyncStorage.setItem('theme', theme);
};

const loadPreference = async () => {
  return await AsyncStorage.getItem('theme');
};

希少度: 非常に一般的 難易度: 簡単


19. FlatListScrollViewの違いは何ですか?

回答:

  • ScrollView:
    • すべての子を一度にレンダリング
    • 小さなリストに適している
    • 大きなリストではメモリを大量に消費する
  • FlatList:
    • 表示されているアイテムのみをレンダリング(遅延ロード)
    • 大きなリストに効率的
    • 組み込みの最適化
// ScrollView - すべてをレンダリング
<ScrollView>
  {items.map(item => (
    <View key={item.id}>
      <Text>{item.name}</Text>
    </View>
  ))}
</ScrollView>

// FlatList - 表示されているアイテムのみをレンダリング
<FlatList
  data={items}
  renderItem={({ item }) => (
    <View>
      <Text>{item.name}</Text>
    </View>
  )}
  keyExtractor={item => item.id}
  // パフォーマンスの最適化
  initialNumToRender={10}
  maxToRenderPerBatch={10}
  windowSize={5}
/>

希少度: 非常に一般的 難易度: 簡単


20. フォームとユーザー入力を処理するにはどうすればよいですか?

回答: 状態を持つ制御されたコンポーネントを使用します。

import { useState } from 'react';
import { View, TextInput, Button, Text } from 'react-native';

function LoginForm() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [errors, setErrors] = useState({});
  
  const validate = () => {
    const newErrors = {};
    
    if (!email) {
      newErrors.email = 'Email is required';
    } else if (!/\S+@\S+\.\S+/.test(email)) {
      newErrors.email = 'Email is invalid';
    }
    
    if (!password) {
      newErrors.password = 'Password is required';
    } else if (password.length < 6) {
      newErrors.password = 'Password must be at least 6 characters';
    }
    
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };
  
  const handleSubmit = () => {
    if (validate()) {
      console.log('Form submitted:', { email, password });
      // APIに送信
    }
  };
  
  return (
    <View>
      <TextInput
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        keyboardType="email-address"
        autoCapitalize="none"
      />
      {errors.email && <Text style={{ color: 'red' }}>{errors.email}</Text>}
      
      <TextInput
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
      />
      {errors.password && <Text style={{ color: 'red' }}>{errors.password}</Text>}
      
      <Button title="Login" onPress={handleSubmit} />
    </View>
  );
}

希少度: 非常に一般的 難易度: 中程度

Newsletter subscription

実際に機能する週次のキャリアのヒント

最新の洞察をメールボックスに直接お届けします

次の面接は履歴書一つで決まる

数分でプロフェッショナルで最適化された履歴書を作成。デザインスキルは不要—証明された結果だけ。

私の履歴書を作成

この投稿を共有

75%のATS不採用率を克服

4件中3件の履歴書は人の目に触れることがありません。当社のキーワード最適化により通過率が最大80%向上し、採用担当者に確実にあなたの可能性を見てもらえます。